summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deluge/__rpcapi.py4
-rw-r--r--deluge/_libtorrent.py4
-rw-r--r--deluge/bencode.py16
-rw-r--r--deluge/common.py294
-rw-r--r--deluge/component.py59
-rw-r--r--deluge/config.py32
-rw-r--r--deluge/configmanager.py7
-rw-r--r--deluge/core/alertmanager.py24
-rw-r--r--deluge/core/authmanager.py37
-rw-r--r--deluge/core/core.py181
-rw-r--r--deluge/core/daemon.py22
-rw-r--r--deluge/core/daemon_entry.py36
-rw-r--r--deluge/core/eventmanager.py7
-rw-r--r--deluge/core/filtermanager.py31
-rw-r--r--deluge/core/pluginmanager.py3
-rw-r--r--deluge/core/preferencesmanager.py108
-rw-r--r--deluge/core/rpcserver.py97
-rw-r--r--deluge/core/torrent.py231
-rw-r--r--deluge/core/torrentmanager.py304
-rw-r--r--deluge/crypto_utils.py29
-rw-r--r--deluge/decorators.py43
-rw-r--r--deluge/error.py9
-rw-r--r--deluge/event.py23
-rw-r--r--deluge/httpdownloader.py70
-rw-r--r--deluge/log.py60
-rw-r--r--deluge/maketorrent.py17
-rw-r--r--deluge/metafile.py33
-rw-r--r--deluge/path_chooser_common.py5
-rw-r--r--deluge/pluginmanagerbase.py36
-rw-r--r--deluge/plugins/AutoAdd/deluge/plugins/autoadd/__init__.py3
-rw-r--r--deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py83
-rw-r--r--deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py218
-rw-r--r--deluge/plugins/AutoAdd/setup.py4
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/__init__.py3
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py70
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/core.py67
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/decompressers.py6
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/detect.py12
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/gtkui.py88
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/peerguardian.py1
-rw-r--r--deluge/plugins/Blocklist/deluge/plugins/blocklist/readers.py9
-rw-r--r--deluge/plugins/Blocklist/setup.py3
-rw-r--r--deluge/plugins/Execute/deluge/plugins/execute/__init__.py3
-rw-r--r--deluge/plugins/Execute/deluge/plugins/execute/core.py33
-rw-r--r--deluge/plugins/Execute/deluge/plugins/execute/gtkui.py13
-rw-r--r--deluge/plugins/Execute/setup.py5
-rw-r--r--deluge/plugins/Extractor/deluge/plugins/extractor/__init__.py3
-rw-r--r--deluge/plugins/Extractor/deluge/plugins/extractor/core.py59
-rw-r--r--deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py28
-rw-r--r--deluge/plugins/Extractor/setup.py5
-rw-r--r--deluge/plugins/Label/deluge/plugins/label/__init__.py3
-rw-r--r--deluge/plugins/Label/deluge/plugins/label/core.py52
-rw-r--r--deluge/plugins/Label/deluge/plugins/label/gtkui/label_config.py4
-rw-r--r--deluge/plugins/Label/deluge/plugins/label/gtkui/sidebar_menu.py67
-rw-r--r--deluge/plugins/Label/setup.py5
-rw-r--r--deluge/plugins/Notifications/deluge/plugins/notifications/__init__.py3
-rw-r--r--deluge/plugins/Notifications/deluge/plugins/notifications/common.py32
-rw-r--r--deluge/plugins/Notifications/deluge/plugins/notifications/core.py46
-rw-r--r--deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py331
-rw-r--r--deluge/plugins/Notifications/deluge/plugins/notifications/test.py17
-rwxr-xr-xdeluge/plugins/Notifications/setup.py5
-rw-r--r--deluge/plugins/Scheduler/deluge/plugins/scheduler/__init__.py3
-rw-r--r--deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py23
-rw-r--r--deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py75
-rw-r--r--deluge/plugins/Scheduler/setup.py5
-rw-r--r--deluge/plugins/Stats/deluge/plugins/stats/__init__.py3
-rw-r--r--deluge/plugins/Stats/deluge/plugins/stats/core.py21
-rw-r--r--deluge/plugins/Stats/deluge/plugins/stats/graph.py22
-rw-r--r--deluge/plugins/Stats/deluge/plugins/stats/gtkui.py55
-rw-r--r--deluge/plugins/Stats/deluge/plugins/stats/tests/test_stats.py1
-rw-r--r--deluge/plugins/Stats/setup.py5
-rw-r--r--deluge/plugins/Toggle/deluge/plugins/toggle/__init__.py3
-rw-r--r--deluge/plugins/Toggle/deluge/plugins/toggle/core.py3
-rw-r--r--deluge/plugins/Toggle/deluge/plugins/toggle/gtkui.py7
-rw-r--r--deluge/plugins/Toggle/setup.py5
-rw-r--r--deluge/plugins/WebUi/deluge/plugins/webui/__init__.py3
-rw-r--r--deluge/plugins/WebUi/deluge/plugins/webui/core.py6
-rw-r--r--deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py34
-rw-r--r--deluge/plugins/WebUi/deluge/plugins/webui/tests/test_plugin_webui.py3
-rw-r--r--deluge/plugins/WebUi/setup.py5
-rw-r--r--deluge/plugins/pluginbase.py2
-rw-r--r--deluge/rencode.py89
-rw-r--r--deluge/scripts/create_plugin.py26
-rw-r--r--deluge/scripts/deluge_remote.py45
-rw-r--r--deluge/tests/basetest.py5
-rw-r--r--deluge/tests/common.py55
-rw-r--r--deluge/tests/common_web.py5
-rw-r--r--deluge/tests/daemon_base.py17
-rw-r--r--deluge/tests/test_alertmanager.py1
-rw-r--r--deluge/tests/test_authmanager.py5
-rw-r--r--deluge/tests/test_bencode.py1
-rw-r--r--deluge/tests/test_client.py46
-rw-r--r--deluge/tests/test_common.py49
-rw-r--r--deluge/tests/test_component.py43
-rw-r--r--deluge/tests/test_config.py9
-rw-r--r--deluge/tests/test_core.py81
-rw-r--r--deluge/tests/test_error.py11
-rw-r--r--deluge/tests/test_files_tab.py50
-rw-r--r--deluge/tests/test_httpdownloader.py14
-rw-r--r--deluge/tests/test_json_api.py39
-rw-r--r--deluge/tests/test_log.py1
-rw-r--r--deluge/tests/test_maketorrent.py2
-rw-r--r--deluge/tests/test_metafile.py2
-rw-r--r--deluge/tests/test_plugin_metadata.py1
-rw-r--r--deluge/tests/test_rpcserver.py13
-rw-r--r--deluge/tests/test_security.py4
-rw-r--r--deluge/tests/test_sessionproxy.py13
-rw-r--r--deluge/tests/test_torrent.py103
-rw-r--r--deluge/tests/test_torrentmanager.py73
-rw-r--r--deluge/tests/test_torrentview.py161
-rw-r--r--deluge/tests/test_transfer.py119
-rw-r--r--deluge/tests/test_ui_common.py10
-rw-r--r--deluge/tests/test_ui_console_fields.py12
-rw-r--r--deluge/tests/test_ui_entry.py68
-rw-r--r--deluge/tests/test_web_api.py46
-rw-r--r--deluge/tests/test_webserver.py5
-rw-r--r--deluge/tests/twisted/plugins/delugereporter.py5
-rw-r--r--deluge/transfer.py23
-rw-r--r--deluge/ui/Win32IconImagePlugin.py57
-rw-r--r--deluge/ui/baseargparser.py86
-rw-r--r--deluge/ui/client.py92
-rw-r--r--deluge/ui/common.py240
-rw-r--r--deluge/ui/console/cmdline/command.py21
-rw-r--r--deluge/ui/console/cmdline/commands/add.py46
-rw-r--r--deluge/ui/console/cmdline/commands/cache.py4
-rw-r--r--deluge/ui/console/cmdline/commands/config.py24
-rw-r--r--deluge/ui/console/cmdline/commands/connect.py22
-rw-r--r--deluge/ui/console/cmdline/commands/debug.py4
-rw-r--r--deluge/ui/console/cmdline/commands/gui.py1
-rw-r--r--deluge/ui/console/cmdline/commands/halt.py6
-rw-r--r--deluge/ui/console/cmdline/commands/help.py15
-rw-r--r--deluge/ui/console/cmdline/commands/info.py146
-rw-r--r--deluge/ui/console/cmdline/commands/manage.py33
-rw-r--r--deluge/ui/console/cmdline/commands/move.py16
-rw-r--r--deluge/ui/console/cmdline/commands/pause.py5
-rw-r--r--deluge/ui/console/cmdline/commands/plugin.py46
-rw-r--r--deluge/ui/console/cmdline/commands/quit.py1
-rw-r--r--deluge/ui/console/cmdline/commands/recheck.py8
-rw-r--r--deluge/ui/console/cmdline/commands/resume.py5
-rw-r--r--deluge/ui/console/cmdline/commands/rm.py35
-rw-r--r--deluge/ui/console/cmdline/commands/status.py35
-rw-r--r--deluge/ui/console/cmdline/commands/update_tracker.py5
-rw-r--r--deluge/ui/console/console.py65
-rw-r--r--deluge/ui/console/main.py247
-rw-r--r--deluge/ui/console/modes/add_util.py22
-rw-r--r--deluge/ui/console/modes/addtorrents.py52
-rw-r--r--deluge/ui/console/modes/basemode.py48
-rw-r--r--deluge/ui/console/modes/cmdline.py91
-rw-r--r--deluge/ui/console/modes/connectionmanager.py25
-rw-r--r--deluge/ui/console/modes/eventview.py1
-rw-r--r--deluge/ui/console/modes/preferences/preference_panes.py438
-rw-r--r--deluge/ui/console/modes/preferences/preferences.py80
-rw-r--r--deluge/ui/console/modes/torrentdetail.py246
-rw-r--r--deluge/ui/console/modes/torrentlist/__init__.py2
-rw-r--r--deluge/ui/console/modes/torrentlist/add_torrents_popup.py42
-rw-r--r--deluge/ui/console/modes/torrentlist/filtersidebar.py38
-rw-r--r--deluge/ui/console/modes/torrentlist/queue_mode.py70
-rw-r--r--deluge/ui/console/modes/torrentlist/search_mode.py40
-rw-r--r--deluge/ui/console/modes/torrentlist/torrentactions.py83
-rw-r--r--deluge/ui/console/modes/torrentlist/torrentlist.py38
-rw-r--r--deluge/ui/console/modes/torrentlist/torrentview.py65
-rw-r--r--deluge/ui/console/modes/torrentlist/torrentviewcolumns.py96
-rw-r--r--deluge/ui/console/parser.py4
-rw-r--r--deluge/ui/console/utils/colors.py38
-rw-r--r--deluge/ui/console/utils/column.py7
-rw-r--r--deluge/ui/console/utils/format_utils.py10
-rw-r--r--deluge/ui/console/widgets/fields.py407
-rw-r--r--deluge/ui/console/widgets/inputpane.py136
-rw-r--r--deluge/ui/console/widgets/popup.py73
-rw-r--r--deluge/ui/console/widgets/sidebar.py14
-rw-r--r--deluge/ui/console/widgets/statusbars.py8
-rw-r--r--deluge/ui/console/widgets/window.py37
-rw-r--r--deluge/ui/coreconfig.py5
-rw-r--r--deluge/ui/gtkui/__init__.py6
-rw-r--r--deluge/ui/gtkui/aboutdialog.py993
-rw-r--r--deluge/ui/gtkui/addtorrentdialog.py279
-rw-r--r--deluge/ui/gtkui/common.py70
-rw-r--r--deluge/ui/gtkui/connectionmanager.py92
-rw-r--r--deluge/ui/gtkui/createtorrentdialog.py134
-rw-r--r--deluge/ui/gtkui/details_tab.py8
-rw-r--r--deluge/ui/gtkui/dialogs.py49
-rw-r--r--deluge/ui/gtkui/edittrackersdialog.py35
-rw-r--r--deluge/ui/gtkui/files_tab.py133
-rw-r--r--deluge/ui/gtkui/filtertreeview.py49
-rw-r--r--deluge/ui/gtkui/gtkui.py32
-rw-r--r--deluge/ui/gtkui/ipcinterface.py15
-rw-r--r--deluge/ui/gtkui/listview.py260
-rw-r--r--deluge/ui/gtkui/mainwindow.py92
-rw-r--r--deluge/ui/gtkui/menubar.py212
-rw-r--r--deluge/ui/gtkui/menubar_osx.py9
-rw-r--r--deluge/ui/gtkui/new_release_dialog.py18
-rw-r--r--deluge/ui/gtkui/options_tab.py52
-rw-r--r--deluge/ui/gtkui/path_chooser.py51
-rwxr-xr-xdeluge/ui/gtkui/path_combo_chooser.py475
-rw-r--r--deluge/ui/gtkui/peers_tab.py97
-rw-r--r--deluge/ui/gtkui/piecesbar.py25
-rw-r--r--deluge/ui/gtkui/pluginmanager.py15
-rw-r--r--deluge/ui/gtkui/preferences.py654
-rw-r--r--deluge/ui/gtkui/queuedtorrents.py24
-rw-r--r--deluge/ui/gtkui/removetorrentdialog.py15
-rw-r--r--deluge/ui/gtkui/sidebar.py1
-rw-r--r--deluge/ui/gtkui/status_tab.py56
-rw-r--r--deluge/ui/gtkui/statusbar.py148
-rw-r--r--deluge/ui/gtkui/systemtray.py118
-rw-r--r--deluge/ui/gtkui/toolbar.py6
-rw-r--r--deluge/ui/gtkui/torrentdetails.py27
-rw-r--r--deluge/ui/gtkui/torrentview.py239
-rw-r--r--deluge/ui/gtkui/torrentview_data_funcs.py25
-rw-r--r--deluge/ui/gtkui/trackers_tab.py9
-rw-r--r--deluge/ui/hostlist.py31
-rw-r--r--deluge/ui/sessionproxy.py32
-rw-r--r--deluge/ui/tracker_icons.py68
-rw-r--r--deluge/ui/translations_util.py21
-rw-r--r--deluge/ui/ui.py2
-rw-r--r--deluge/ui/ui_entry.py27
-rw-r--r--deluge/ui/web/auth.py13
-rw-r--r--deluge/ui/web/common.py22
-rw-r--r--deluge/ui/web/json_api.py92
-rw-r--r--deluge/ui/web/pluginmanager.py57
-rw-r--r--deluge/ui/web/server.py111
-rw-r--r--deluge/ui/web/web.py41
-rw-r--r--docs/source/conf.py35
-rwxr-xr-xgen_web_gettext.py24
-rwxr-xr-xgenerate_pot.py6
-rwxr-xr-xminify_web_js.py21
-rwxr-xr-xmsgfmt.py35
-rwxr-xr-xpackaging/source/make_release.py15
-rw-r--r--packaging/win32/deluge-bbfreeze.py89
-rw-r--r--pyproject.toml8
-rw-r--r--setup.cfg23
-rwxr-xr-xsetup.py137
-rw-r--r--tox.ini15
-rwxr-xr-xversion.py2
233 files changed, 9459 insertions, 4111 deletions
diff --git a/deluge/__rpcapi.py b/deluge/__rpcapi.py
index 5f2934a32..b279d23ea 100644
--- a/deluge/__rpcapi.py
+++ b/deluge/__rpcapi.py
@@ -18,9 +18,7 @@ class RpcApi(object):
def scan_for_methods(obj):
- methods = {
- '__doc__': 'Methods available in %s' % obj.__name__.lower(),
- }
+ methods = {'__doc__': 'Methods available in %s' % obj.__name__.lower()}
for d in dir(obj):
if not hasattr(getattr(obj, d), '_rpcserver_export'):
continue
diff --git a/deluge/_libtorrent.py b/deluge/_libtorrent.py
index 02edf187c..f155feedb 100644
--- a/deluge/_libtorrent.py
+++ b/deluge/_libtorrent.py
@@ -28,4 +28,6 @@ REQUIRED_VERSION = '1.1.2.0'
LT_VERSION = lt.__version__
if VersionSplit(LT_VERSION) < VersionSplit(REQUIRED_VERSION):
- raise ImportError('Deluge %s requires libtorrent >= %s' % (get_version(), REQUIRED_VERSION))
+ raise ImportError(
+ 'Deluge %s requires libtorrent >= %s' % (get_version(), REQUIRED_VERSION)
+ )
diff --git a/deluge/bencode.py b/deluge/bencode.py
index 997f2f2c0..2cb30f5a1 100644
--- a/deluge/bencode.py
+++ b/deluge/bencode.py
@@ -33,9 +33,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)
@@ -43,25 +43,25 @@ 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)
+ return (x[colon : colon + n], colon + n)
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)
diff --git a/deluge/common.py b/deluge/common.py
index 6de58a9c5..6bb2fb043 100644
--- a/deluge/common.py
+++ b/deluge/common.py
@@ -44,6 +44,7 @@ except ImportError:
# see: https://twistedmatrix.com/trac/ticket/9209
if platform.system() in ('Windows', 'Microsoft'):
from certifi import where
+
os.environ['SSL_CERT_FILE'] = where()
DBUS_FILEMAN = None
@@ -56,7 +57,9 @@ if platform.system() not in ('Windows', 'Microsoft', 'Darwin'):
else:
try:
bus = dbus.SessionBus()
- DBUS_FILEMAN = bus.get_object('org.freedesktop.FileManager1', '/org/freedesktop/FileManager1')
+ DBUS_FILEMAN = bus.get_object(
+ 'org.freedesktop.FileManager1', '/org/freedesktop/FileManager1'
+ )
except dbus.DBusException:
pass
@@ -101,6 +104,7 @@ def get_default_config_dir(filename=None):
"""
if windows_check():
+
def save_config_path(resource):
app_data_path = os.environ.get('APPDATA')
if not app_data_path:
@@ -116,6 +120,7 @@ def get_default_config_dir(filename=None):
app_data_path = app_data_reg[0]
winreg.CloseKey(hkey)
return os.path.join(app_data_path, resource)
+
else:
from xdg.BaseDirectory import save_config_path
if not filename:
@@ -136,11 +141,14 @@ def get_default_download_dir():
download_dir = ''
if not windows_check():
from xdg.BaseDirectory import xdg_config_home
+
try:
with open(os.path.join(xdg_config_home, 'user-dirs.dirs'), 'r') as _file:
for line in _file:
if not line.startswith('#') and line.startswith('XDG_DOWNLOAD_DIR'):
- download_dir = os.path.expandvars(line.partition('=')[2].rstrip().strip('"'))
+ download_dir = os.path.expandvars(
+ line.partition('=')[2].rstrip().strip('"')
+ )
break
except IOError:
pass
@@ -151,46 +159,50 @@ def get_default_download_dir():
def archive_files(arc_name, filepaths):
- """Compress a list of filepaths into timestamped tarball in config dir.
+ """Compress a list of filepaths into timestamped tarball in config dir.
- The archiving config directory is 'archive'.
+ The archiving config directory is 'archive'.
- Args:
- arc_name (str): The archive output filename (appended with timestamp).
- filepaths (list): A list of the files to be archived into tarball.
+ Args:
+ arc_name (str): The archive output filename (appended with timestamp).
+ filepaths (list): A list of the files to be archived into tarball.
- Returns:
- str: The full archive filepath.
+ Returns:
+ str: The full archive filepath.
- """
+ """
- from deluge.configmanager import get_config_dir
+ from deluge.configmanager import get_config_dir
- # Set archive compression to lzma with bz2 fallback.
- arc_comp = 'xz' if not PY2 else 'bz2'
+ # Set archive compression to lzma with bz2 fallback.
+ arc_comp = 'xz' if not PY2 else 'bz2'
- archive_dir = os.path.join(get_config_dir(), 'archive')
- timestamp = datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')
- arc_filepath = os.path.join(archive_dir, arc_name + '-' + timestamp + '.tar.' + arc_comp)
- max_num_arcs = 20
+ archive_dir = os.path.join(get_config_dir(), 'archive')
+ timestamp = (
+ datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')
+ )
+ arc_filepath = os.path.join(
+ archive_dir, arc_name + '-' + timestamp + '.tar.' + arc_comp
+ )
+ max_num_arcs = 20
- if not os.path.exists(archive_dir):
- os.makedirs(archive_dir)
- else:
- old_arcs = glob.glob(os.path.join(archive_dir, arc_name) + '*')
- if len(old_arcs) > max_num_arcs:
- # TODO: Remove oldest timestamped archives.
- log.warning('More than %s tarballs in config archive', max_num_arcs)
+ if not os.path.exists(archive_dir):
+ os.makedirs(archive_dir)
+ else:
+ old_arcs = glob.glob(os.path.join(archive_dir, arc_name) + '*')
+ if len(old_arcs) > max_num_arcs:
+ # TODO: Remove oldest timestamped archives.
+ log.warning('More than %s tarballs in config archive', max_num_arcs)
- try:
- with tarfile.open(arc_filepath, 'w:' + arc_comp) as tf:
- for filepath in filepaths:
- tf.add(filepath, arcname=os.path.basename(filepath))
- except OSError:
- log.error('Problem occurred archiving filepaths: %s', filepaths)
- return False
- else:
- return arc_filepath
+ try:
+ with tarfile.open(arc_filepath, 'w:' + arc_comp) as tf:
+ for filepath in filepaths:
+ tf.add(filepath, arcname=os.path.basename(filepath))
+ except OSError:
+ log.error('Problem occurred archiving filepaths: %s', filepaths)
+ return False
+ else:
+ return arc_filepath
def windows_check():
@@ -254,7 +266,7 @@ def get_os_version():
elif linux_check():
os_version = platform.linux_distribution()
else:
- os_version = (platform.release(), )
+ os_version = (platform.release(),)
return ' '.join(filter(None, os_version))
@@ -281,7 +293,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]))
)
@@ -301,8 +313,12 @@ def open_file(path, timestamp=None):
if timestamp is None:
timestamp = int(time.time())
env = os.environ.copy()
- env['DESKTOP_STARTUP_ID'] = '%s-%u-%s-xdg_open_TIME%d' % \
- (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
+ env['DESKTOP_STARTUP_ID'] = '%s-%u-%s-xdg_open_TIME%d' % (
+ os.path.basename(sys.argv[0]),
+ os.getpid(),
+ os.uname()[1],
+ timestamp,
+ )
subprocess.Popen(['xdg-open', '%s' % path], env=env)
@@ -321,10 +337,17 @@ def show_file(path, timestamp=None):
else:
if timestamp is None:
timestamp = int(time.time())
- startup_id = '%s_%u_%s-dbus_TIME%d' % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
+ startup_id = '%s_%u_%s-dbus_TIME%d' % (
+ os.path.basename(sys.argv[0]),
+ os.getpid(),
+ os.uname()[1],
+ timestamp,
+ )
if DBUS_FILEMAN:
paths = [urljoin('file:', pathname2url(path))]
- DBUS_FILEMAN.ShowItems(paths, startup_id, dbus_interface='org.freedesktop.FileManager1')
+ DBUS_FILEMAN.ShowItems(
+ paths, startup_id, dbus_interface='org.freedesktop.FileManager1'
+ )
else:
env = os.environ.copy()
env['DESKTOP_STARTUP_ID'] = startup_id.replace('dbus', 'xdg-open')
@@ -341,6 +364,7 @@ def open_url_in_browser(url):
"""
import webbrowser
+
webbrowser.open(url)
@@ -396,13 +420,29 @@ def fsize(fsize_b, precision=1, shortform=False):
"""
if fsize_b >= 1024 ** 4:
- return '%.*f %s' % (precision, fsize_b / 1024 ** 4, tib_txt_short if shortform else tib_txt)
+ return '%.*f %s' % (
+ precision,
+ fsize_b / 1024 ** 4,
+ tib_txt_short if shortform else tib_txt,
+ )
elif fsize_b >= 1024 ** 3:
- return '%.*f %s' % (precision, fsize_b / 1024 ** 3, gib_txt_short if shortform else gib_txt)
+ return '%.*f %s' % (
+ precision,
+ fsize_b / 1024 ** 3,
+ gib_txt_short if shortform else gib_txt,
+ )
elif fsize_b >= 1024 ** 2:
- return '%.*f %s' % (precision, fsize_b / 1024 ** 2, mib_txt_short if shortform else mib_txt)
+ return '%.*f %s' % (
+ precision,
+ fsize_b / 1024 ** 2,
+ mib_txt_short if shortform else mib_txt,
+ )
elif fsize_b >= 1024:
- return '%.*f %s' % (precision, fsize_b / 1024, kib_txt_short if shortform else kib_txt)
+ return '%.*f %s' % (
+ precision,
+ fsize_b / 1024,
+ kib_txt_short if shortform else kib_txt,
+ )
else:
return '%d %s' % (fsize_b, byte_txt)
@@ -425,7 +465,7 @@ def fpcnt(dec, precision=2):
"""
- pcnt = (dec * 100)
+ pcnt = dec * 100
if pcnt == 0 or pcnt == 100:
precision = 0
return '%.*f%%' % (precision, pcnt)
@@ -447,13 +487,29 @@ def fspeed(bps, precision=1, shortform=False):
"""
if bps < 1024 ** 2:
- return '%.*f %s' % (precision, bps / 1024, _('K/s') if shortform else _('KiB/s'))
+ return '%.*f %s' % (
+ precision,
+ bps / 1024,
+ _('K/s') if shortform else _('KiB/s'),
+ )
elif bps < 1024 ** 3:
- return '%.*f %s' % (precision, bps / 1024 ** 2, _('M/s') if shortform else _('MiB/s'))
+ return '%.*f %s' % (
+ precision,
+ bps / 1024 ** 2,
+ _('M/s') if shortform else _('MiB/s'),
+ )
elif bps < 1024 ** 4:
- return '%.*f %s' % (precision, bps / 1024 ** 3, _('G/s') if shortform else _('GiB/s'))
+ return '%.*f %s' % (
+ precision,
+ bps / 1024 ** 3,
+ _('G/s') if shortform else _('GiB/s'),
+ )
else:
- return '%.*f %s' % (precision, bps / 1024 ** 4, _('T/s') if shortform else _('TiB/s'))
+ return '%.*f %s' % (
+ precision,
+ bps / 1024 ** 4,
+ _('T/s') if shortform else _('TiB/s'),
+ )
def fpeer(num_peers, total_peers):
@@ -566,17 +622,17 @@ def tokenize(text):
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},
+ {'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},
]
@@ -706,9 +762,9 @@ def get_magnet_info(uri):
info_hash = None
trackers = {}
tier = 0
- for param in uri[len(MAGNET_SCHEME):].split('&'):
+ for param in uri[len(MAGNET_SCHEME) :].split('&'):
if param.startswith(XT_BTIH_PARAM):
- xt_hash = param[len(XT_BTIH_PARAM):]
+ xt_hash = param[len(XT_BTIH_PARAM) :]
if len(xt_hash) == 32:
try:
infohash_str = base64.b32decode(xt_hash.upper())
@@ -721,9 +777,9 @@ def get_magnet_info(uri):
else:
break
elif param.startswith(DN_PARAM):
- name = unquote_plus(param[len(DN_PARAM):])
+ name = unquote_plus(param[len(DN_PARAM) :])
elif param.startswith(TR_PARAM):
- tracker = unquote_plus(param[len(TR_PARAM):])
+ tracker = unquote_plus(param[len(TR_PARAM) :])
trackers[tracker] = tier
tier += 1
elif param.startswith(tr0_param):
@@ -736,7 +792,12 @@ def get_magnet_info(uri):
if info_hash:
if not name:
name = info_hash
- return {'name': name, 'info_hash': info_hash, 'files_tree': '', 'trackers': trackers}
+ return {
+ 'name': name,
+ 'info_hash': info_hash,
+ 'files_tree': '',
+ 'trackers': trackers,
+ }
else:
return {}
@@ -758,11 +819,7 @@ def create_magnet_uri(infohash, name=None, trackers=None):
except TypeError:
infohash.encode('utf-8')
- uri = [
- MAGNET_SCHEME,
- XT_BTIH_PARAM,
- base64.b32encode(infohash).decode('utf-8'),
- ]
+ uri = [MAGNET_SCHEME, XT_BTIH_PARAM, base64.b32encode(infohash).decode('utf-8')]
if name:
uri.extend(['&', DN_PARAM, name])
if trackers:
@@ -817,6 +874,7 @@ def free_space(path):
if windows_check():
from win32file import GetDiskFreeSpaceEx
+
return GetDiskFreeSpaceEx(path)[0]
else:
disk_data = os.statvfs(path.encode('utf8'))
@@ -860,6 +918,7 @@ def is_ipv4(ip):
"""
import socket
+
try:
if windows_check():
return socket.inet_aton(ip)
@@ -888,6 +947,7 @@ def is_ipv6(ip):
import ipaddress
except ImportError:
import socket
+
try:
return socket.inet_pton(socket.AF_INET6, ip)
except (socket.error, AttributeError):
@@ -969,8 +1029,7 @@ def utf8_encode_structure(data):
return type(data)([utf8_encode_structure(d) for d in data])
elif isinstance(data, dict):
return {
- utf8_encode_structure(k): utf8_encode_structure(v)
- for k, v in data.items()
+ utf8_encode_structure(k): utf8_encode_structure(v) for k, v in data.items()
}
elif not isinstance(data, bytes):
try:
@@ -989,6 +1048,7 @@ class VersionSplit(object):
:type ver: string
"""
+
def __init__(self, ver):
version_re = re.compile(
r"""
@@ -1001,7 +1061,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
@@ -1086,48 +1147,52 @@ def create_localclient_account(append=False):
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',
+ ':'.join(
+ [
+ 'localclient',
+ sha(str(random.random()).encode('utf8')).hexdigest(),
+ str(AUTH_LEVEL_ADMIN),
+ ]
+ )
+ + '\n'
)
_file.flush()
os.fsync(_file.fileno())
def get_localhost_auth():
- """Grabs the localclient auth line from the 'auth' file and creates a localhost uri.
+ """Grabs the localclient auth line from the 'auth' file and creates a localhost uri.
- Returns:
- tuple: With the username and password to login as.
+ Returns:
+ tuple: With the username and password to login as.
+ """
+ from deluge.configmanager import get_config_dir
- """
- from deluge.configmanager import get_config_dir
- auth_file = get_config_dir('auth')
- if not os.path.exists(auth_file):
- from deluge.common import create_localclient_account
- create_localclient_account()
+ auth_file = get_config_dir('auth')
+ if not os.path.exists(auth_file):
+ from deluge.common import create_localclient_account
- with open(auth_file) as auth:
- for line in auth:
- line = line.strip()
- if line.startswith('#') or not line:
- # This is a comment or blank line
- continue
+ create_localclient_account()
- lsplit = line.split(':')
+ with open(auth_file) as auth:
+ for line in auth:
+ line = line.strip()
+ if line.startswith('#') or not line:
+ # This is a comment or blank line
+ continue
- if len(lsplit) == 2:
- username, password = lsplit
- elif len(lsplit) == 3:
- username, password, level = lsplit
- else:
- log.error('Your auth file is malformed: Incorrect number of fields!')
- continue
+ lsplit = line.split(':')
- if username == 'localclient':
- return (username, password)
+ if len(lsplit) == 2:
+ username, password = lsplit
+ elif len(lsplit) == 3:
+ username, password, level = lsplit
+ else:
+ log.error('Your auth file is malformed: Incorrect number of fields!')
+ continue
+
+ if username == 'localclient':
+ return (username, password)
def set_env_variable(name, value):
@@ -1169,9 +1234,16 @@ def set_env_variable(name, value):
if result == 0:
raise Warning
except Exception:
- log.warning('Failed to set Env Var \'%s\' (\'kernel32.SetEnvironmentVariableW\')', name)
+ log.warning(
+ 'Failed to set Env Var \'%s\' (\'kernel32.SetEnvironmentVariableW\')',
+ name,
+ )
else:
- log.debug('Set Env Var \'%s\' to \'%s\' (\'kernel32.SetEnvironmentVariableW\')', name, value)
+ log.debug(
+ 'Set Env Var \'%s\' to \'%s\' (\'kernel32.SetEnvironmentVariableW\')',
+ name,
+ value,
+ )
# Update the copy maintained by msvcrt (used by gtk+ runtime)
try:
@@ -1191,9 +1263,13 @@ def set_env_variable(name, value):
if result != 0:
raise Warning
except Exception:
- log.warning('Failed to set Env Var \'%s\' (\'%s._putenv\')', name, msvcrtname)
+ log.warning(
+ 'Failed to set Env Var \'%s\' (\'%s._putenv\')', name, msvcrtname
+ )
else:
- log.debug('Set Env Var \'%s\' to \'%s\' (\'%s._putenv\')', name, value, msvcrtname)
+ log.debug(
+ 'Set Env Var \'%s\' to \'%s\' (\'%s._putenv\')', name, value, msvcrtname
+ )
def unicode_argv():
@@ -1219,8 +1295,7 @@ def unicode_argv():
if argc.value > 0:
# Remove Python executable and commands if present
start = argc.value - len(sys.argv)
- return [argv[i] for i in
- range(start, argc.value)]
+ return [argv[i] for i in range(start, argc.value)]
else:
# On other platforms, we have to find the likely encoding of the args and decode
# First check if sys.stdout or stdin have encoding set
@@ -1253,6 +1328,7 @@ def run_profiled(func, *args, **kwargs):
"""
if kwargs.get('do_profile', True) is not False:
import cProfile
+
profiler = cProfile.Profile()
def on_shutdown():
@@ -1264,6 +1340,7 @@ def run_profiled(func, *args, **kwargs):
else:
import pstats
from io import StringIO
+
strio = StringIO()
ps = pstats.Stats(profiler, stream=strio).sort_stats('cumulative')
ps.print_stats()
@@ -1291,6 +1368,7 @@ def is_process_running(pid):
if windows_check():
from win32process import EnumProcesses
+
return pid in EnumProcesses()
else:
try:
diff --git a/deluge/component.py b/deluge/component.py
index 8264a5e64..72aa3246a 100644
--- a/deluge/component.py
+++ b/deluge/component.py
@@ -27,7 +27,6 @@ class ComponentAlreadyRegistered(Exception):
class ComponentException(Exception):
-
def __init__(self, message, tb):
super(ComponentException, self).__init__(message)
self.message = message
@@ -93,6 +92,7 @@ class Component(object):
still be considered in a Started state.
"""
+
def __init__(self, name, interval=1, depend=None):
"""Initialize component.
@@ -146,12 +146,14 @@ 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):
@@ -195,12 +197,14 @@ 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):
@@ -211,12 +215,14 @@ 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):
@@ -250,6 +256,7 @@ class ComponentRegistry(object):
It is used to manage the Components by starting, stopping, pausing and shutting them down.
"""
+
def __init__(self):
self.components = {}
# Stores all of the components that are dependent on a particular component
@@ -270,7 +277,9 @@ class ComponentRegistry(object):
"""
name = obj._component_name
if name in self.components:
- raise ComponentAlreadyRegistered('Component already registered with name %s' % name)
+ raise ComponentAlreadyRegistered(
+ 'Component already registered with name %s' % name
+ )
self.components[obj._component_name] = obj
if obj._component_depend:
@@ -295,6 +304,7 @@ class ComponentRegistry(object):
def on_stop(result, name):
# Component may have been removed, so pop to ensure it doesn't fail
self.components.pop(name, None)
+
return d.addCallback(on_stop, obj._component_name)
else:
return succeed(None)
@@ -364,7 +374,9 @@ class ComponentRegistry(object):
if name in self.components:
if name in self.dependents:
# If other components depend on this component, stop them first
- d = self.stop(self.dependents[name]).addCallback(on_dependents_stopped, name)
+ d = self.stop(self.dependents[name]).addCallback(
+ on_dependents_stopped, name
+ )
deferreds.append(d)
stopped_in_deferred.update(self.dependents[name])
else:
@@ -434,8 +446,11 @@ class ComponentRegistry(object):
Deferred: Fired once all Components have been successfully shut down.
"""
+
def on_stopped(result):
- return DeferredList([comp._component_shutdown() for comp in self.components.values()])
+ return DeferredList(
+ [comp._component_shutdown() for comp in self.components.values()]
+ )
return self.stop(list(self.components)).addCallback(on_stopped)
diff --git a/deluge/config.py b/deluge/config.py
index 45a440d1a..3061bf947 100644
--- a/deluge/config.py
+++ b/deluge/config.py
@@ -121,16 +121,14 @@ class Config(object):
setup to convert old config files. (default: 1)
"""
+
def __init__(self, filename, defaults=None, config_dir=None, file_version=1):
self.__config = {}
self.__set_functions = {}
self.__change_callbacks = []
# These hold the version numbers and they will be set when loaded
- self.__version = {
- 'format': 1,
- 'file': file_version,
- }
+ self.__version = {'format': 1, 'file': file_version}
# This will get set with a reactor.callLater whenever a config option
# is set.
@@ -210,7 +208,9 @@ class Config(object):
global callLater
if callLater is None:
# Must import here and not at the top or it will throw ReactorAlreadyInstalledError
- from twisted.internet.reactor import callLater # pylint: disable=redefined-outer-name
+ from twisted.internet.reactor import (
+ callLater,
+ ) # pylint: disable=redefined-outer-name
# Run the set_function for this key if any
try:
for func in self.__set_functions[key]:
@@ -218,9 +218,11 @@ class Config(object):
except KeyError:
pass
try:
+
def do_change_callbacks(key, value):
for func in self.__change_callbacks:
func(key, value)
+
callLater(0, do_change_callbacks, key, value)
except Exception:
pass
@@ -306,7 +308,9 @@ class Config(object):
global callLater
if callLater is None:
# Must import here and not at the top or it will throw ReactorAlreadyInstalledError
- from twisted.internet.reactor import callLater # pylint: disable=redefined-outer-name
+ from twisted.internet.reactor import (
+ callLater,
+ ) # pylint: disable=redefined-outer-name
# We set the save_timer for 5 seconds if not already set
if not self._save_timer or not self._save_timer.active():
@@ -432,8 +436,11 @@ class Config(object):
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,
+ 'Config %s version: %s.%s loaded: %s',
+ filename,
+ self.__version['format'],
+ self.__version['file'],
+ self.__config,
)
def save(self, filename=None):
@@ -518,7 +525,8 @@ class Config(object):
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,
+ self.__version['file'],
+ input_range,
)
return
@@ -528,7 +536,9 @@ class Config(object):
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,
+ self.__config_file,
+ self.__version['file'],
+ output_version,
)
raise ex
else:
@@ -542,9 +552,11 @@ class Config(object):
@prop
def config(): # pylint: disable=no-method-argument
"""The config dictionary"""
+
def fget(self):
return self.__config
def fdel(self):
return self.save()
+
return locals()
diff --git a/deluge/configmanager.py b/deluge/configmanager.py
index db4de51f6..bbb0389a5 100644
--- a/deluge/configmanager.py
+++ b/deluge/configmanager.py
@@ -95,7 +95,8 @@ class _ConfigManager(object):
# 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_file,
+ defaults,
config_dir=self.config_directory,
file_version=file_version,
)
@@ -108,7 +109,9 @@ _configmanager = _ConfigManager()
def ConfigManager(config, defaults=None, file_version=1): # NOQA: N802
- return _configmanager.get_config(config, defaults=defaults, file_version=file_version)
+ return _configmanager.get_config(
+ config, defaults=defaults, file_version=file_version
+ )
def set_config_dir(directory):
diff --git a/deluge/core/alertmanager.py b/deluge/core/alertmanager.py
index af4fa4287..04e429ea5 100644
--- a/deluge/core/alertmanager.py
+++ b/deluge/core/alertmanager.py
@@ -30,6 +30,7 @@ log = logging.getLogger(__name__)
class AlertManager(component.Component):
"""AlertManager fetches and processes libtorrent alerts"""
+
def __init__(self):
log.debug('AlertManager init...')
component.Component.__init__(self, 'AlertManager', interval=0.3)
@@ -40,13 +41,13 @@ class AlertManager(component.Component):
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
+ 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})
@@ -107,7 +108,10 @@ class AlertManager(component.Component):
if log.isEnabledFor(logging.DEBUG):
log.debug('Alerts queued: %s', num_alerts)
if num_alerts > 0.9 * self.alert_queue_size:
- log.warning('Warning total alerts queued, %s, passes 90%% of queue size.', num_alerts)
+ log.warning(
+ 'Warning total alerts queued, %s, passes 90%% of queue size.',
+ num_alerts,
+ )
# Loop through all alerts in the queue
for alert in alerts:
@@ -126,4 +130,6 @@ class AlertManager(component.Component):
"""Sets the maximum size of the libtorrent alert queue"""
log.info('Alert Queue Size set to %s', queue_size)
self.alert_queue_size = queue_size
- component.get('Core').apply_session_setting('alert_queue_size', self.alert_queue_size)
+ component.get('Core').apply_session_setting(
+ 'alert_queue_size', self.alert_queue_size
+ )
diff --git a/deluge/core/authmanager.py b/deluge/core/authmanager.py
index b241d9a75..0d997c10c 100644
--- a/deluge/core/authmanager.py
+++ b/deluge/core/authmanager.py
@@ -17,8 +17,14 @@ from io import open
import deluge.component as component
import deluge.configmanager as configmanager
-from deluge.common import (AUTH_LEVEL_ADMIN, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_NONE, AUTH_LEVEL_NORMAL,
- AUTH_LEVEL_READONLY, create_localclient_account)
+from deluge.common import (
+ AUTH_LEVEL_ADMIN,
+ AUTH_LEVEL_DEFAULT,
+ AUTH_LEVEL_NONE,
+ AUTH_LEVEL_NORMAL,
+ AUTH_LEVEL_READONLY,
+ create_localclient_account,
+)
from deluge.error import AuthenticationRequired, AuthManagerError, BadLoginError
log = logging.getLogger(__name__)
@@ -50,8 +56,10 @@ class Account(object):
}
def __repr__(self):
- return ('<Account username="%(username)s" authlevel=%(authlevel)s>' %
- {'username': self.username, 'authlevel': self.authlevel})
+ return '<Account username="%(username)s" authlevel=%(authlevel)s>' % {
+ 'username': self.username,
+ 'authlevel': self.authlevel,
+ }
class AuthManager(component.Component):
@@ -99,7 +107,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:
@@ -131,8 +139,7 @@ class AuthManager(component.Component):
raise AuthManagerError('Invalid auth level: %s' % authlevel)
try:
self.__auth[username] = Account(
- username, password,
- AUTH_LEVELS_MAPPING[authlevel],
+ username, password, AUTH_LEVELS_MAPPING[authlevel]
)
self.write_auth_file()
return True
@@ -160,7 +167,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]
@@ -184,7 +191,10 @@ class AuthManager(component.Component):
try:
with open(filepath_tmp, 'w', encoding='utf8') as _file:
for account in self.__auth.values():
- _file.write('%(username)s:%(password)s:%(authlevel_int)s\n' % account.data())
+ _file.write(
+ '%(username)s:%(password)s:%(authlevel_int)s\n'
+ % account.data()
+ )
_file.flush()
os.fsync(_file.fileno())
shutil.move(filepath_tmp, filepath)
@@ -237,7 +247,9 @@ class AuthManager(component.Component):
username, password = lsplit
log.warning(
'Your auth entry for %s contains no auth level, '
- 'using AUTH_LEVEL_DEFAULT(%s)..', username, AUTH_LEVEL_DEFAULT,
+ 'using AUTH_LEVEL_DEFAULT(%s)..',
+ username,
+ AUTH_LEVEL_DEFAULT,
)
if username == 'localclient':
authlevel = AUTH_LEVEL_ADMIN
@@ -259,7 +271,10 @@ class AuthManager(component.Component):
try:
authlevel = AUTH_LEVELS_MAPPING[authlevel]
except KeyError:
- log.error('Your auth file is malformed: %r is not a valid auth level', authlevel)
+ log.error(
+ 'Your auth file is malformed: %r is not a valid auth level',
+ authlevel,
+ )
continue
self.__auth[username] = Account(username, password, authlevel)
diff --git a/deluge/core/core.py b/deluge/core/core.py
index 362bf1dfb..a1571a25e 100644
--- a/deluge/core/core.py
+++ b/deluge/core/core.py
@@ -28,8 +28,13 @@ from deluge._libtorrent import LT_VERSION, lt
from deluge.common import PY2
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.alertmanager import AlertManager
-from deluge.core.authmanager import (AUTH_LEVEL_ADMIN, AUTH_LEVEL_NONE, AUTH_LEVELS_MAPPING,
- AUTH_LEVELS_MAPPING_REVERSE, AuthManager)
+from deluge.core.authmanager import (
+ AUTH_LEVEL_ADMIN,
+ AUTH_LEVEL_NONE,
+ AUTH_LEVELS_MAPPING,
+ AUTH_LEVELS_MAPPING_REVERSE,
+ AuthManager,
+)
from deluge.core.eventmanager import EventManager
from deluge.core.filtermanager import FilterManager
from deluge.core.pluginmanager import PluginManager
@@ -37,8 +42,18 @@ from deluge.core.preferencesmanager import PreferencesManager
from deluge.core.rpcserver import export
from deluge.core.torrentmanager import TorrentManager
from deluge.decorators import deprecated
-from deluge.error import AddTorrentError, DelugeError, InvalidPathError, InvalidTorrentError
-from deluge.event import NewVersionAvailableEvent, SessionPausedEvent, SessionResumedEvent, TorrentQueueChangedEvent
+from deluge.error import (
+ AddTorrentError,
+ DelugeError,
+ InvalidPathError,
+ InvalidTorrentError,
+)
+from deluge.event import (
+ NewVersionAvailableEvent,
+ SessionPausedEvent,
+ SessionResumedEvent,
+ TorrentQueueChangedEvent,
+)
from deluge.httpdownloader import download_file
try:
@@ -99,16 +114,15 @@ DELUGE_VER = deluge.common.get_version()
class Core(component.Component):
- def __init__(self, listen_interface=None, outgoing_interface=None, read_only_config_keys=None):
+ def __init__(
+ self, listen_interface=None, outgoing_interface=None, read_only_config_keys=None
+ ):
component.Component.__init__(self, 'Core')
# Start the libtorrent session.
user_agent = 'Deluge/{} libtorrent/{}'.format(DELUGE_VER, LT_VERSION)
peer_id = self._create_peer_id(DELUGE_VER)
- log.debug(
- 'Starting session (peer_id: %s, user_agent: %s)',
- peer_id, user_agent,
- )
+ log.debug('Starting session (peer_id: %s, user_agent: %s)', peer_id, user_agent)
settings_pack = {
'peer_fingerprint': peer_id,
'user_agent': user_agent,
@@ -139,7 +153,9 @@ class Core(component.Component):
# External IP Address from libtorrent
self.external_ip = None
- self.eventmanager.register_event_handler('ExternalIPEvent', self._on_external_ip_event)
+ self.eventmanager.register_event_handler(
+ 'ExternalIPEvent', self._on_external_ip_event
+ )
# GeoIP instance with db loaded
self.geoip_instance = None
@@ -161,7 +177,10 @@ class Core(component.Component):
self._old_listen_interface = self.config['listen_interface']
self.config['listen_interface'] = listen_interface
else:
- log.error('Invalid listen interface (must be IP Address): %s', listen_interface)
+ log.error(
+ 'Invalid listen interface (must be IP Address): %s',
+ listen_interface,
+ )
self._old_outgoing_interface = None
if outgoing_interface:
@@ -186,10 +205,10 @@ class Core(component.Component):
self.session_status.update({k: 0.0 for k in hit_ratio_keys})
self.session_status_timer_interval = 0.5
- self.session_status_timer = task.LoopingCall(
- self.session.post_session_stats)
+ self.session_status_timer = task.LoopingCall(self.session.post_session_stats)
self.alertmanager.register_handler(
- 'session_stats_alert', self._on_alert_session_stats)
+ 'session_stats_alert', self._on_alert_session_stats
+ )
self.session_rates_timer_interval = 2
self.session_rates_timer = task.LoopingCall(self._update_session_rates)
@@ -264,7 +283,7 @@ class Core(component.Component):
def substitute_chr(string, idx, char):
"""Fast substitute single char in string."""
- return string[:idx] + char + string[idx + 1:]
+ return string[:idx] + char + string[idx + 1 :]
if split.dev:
release_chr = 'D'
@@ -358,16 +377,20 @@ class Core(component.Component):
for rate_key, prev_bytes in list(self._session_prev_bytes.items()):
new_bytes = self.session_status[SESSION_RATES_MAPPING[rate_key]]
self.session_status[rate_key] = (
- new_bytes - prev_bytes) / self.session_rates_timer_interval
+ new_bytes - prev_bytes
+ ) / self.session_rates_timer_interval
# Store current value for next update.
self._session_prev_bytes[rate_key] = new_bytes
def get_new_release(self):
log.debug('get_new_release')
try:
- self.new_release = urlopen(
- 'http://download.deluge-torrent.org/version-2.0',
- ).read().decode().strip()
+ self.new_release = (
+ urlopen('http://download.deluge-torrent.org/version-2.0')
+ .read()
+ .decode()
+ .strip()
+ )
except URLError as ex:
log.debug('Unable to get release info from website: %s', ex)
else:
@@ -376,8 +399,12 @@ class Core(component.Component):
def check_new_release(self):
if self.new_release:
log.debug('new_release: %s', self.new_release)
- if deluge.common.VersionSplit(self.new_release) > deluge.common.VersionSplit(deluge.common.get_version()):
- component.get('EventManager').emit(NewVersionAvailableEvent(self.new_release))
+ if deluge.common.VersionSplit(
+ self.new_release
+ ) > deluge.common.VersionSplit(deluge.common.get_version()):
+ component.get('EventManager').emit(
+ NewVersionAvailableEvent(self.new_release)
+ )
return self.new_release
return False
@@ -403,7 +430,10 @@ 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)
@@ -425,6 +455,7 @@ class Core(component.Component):
The metadata is base64 encoded.
"""
+
def on_metadata(result, result_d):
torrent_id, metadata = result
result_d.callback((torrent_id, b64encode(metadata)))
@@ -456,7 +487,7 @@ 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)
@@ -473,6 +504,7 @@ class Core(component.Component):
Deferred
"""
+
@defer.inlineCallbacks
def add_torrents():
errors = []
@@ -480,12 +512,13 @@ 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.warning('Error when adding torrent: %s', ex)
errors.append(ex)
defer.returnValue(errors)
+
return task.deferLater(reactor, 0, add_torrents)
@export
@@ -583,14 +616,19 @@ class Core(component.Component):
errors = []
for torrent_id in torrent_ids:
try:
- self.torrentmanager.remove(torrent_id, remove_data=remove_data, save_state=False)
+ self.torrentmanager.remove(
+ torrent_id, remove_data=remove_data, save_state=False
+ )
except InvalidTorrentError as ex:
errors.append((torrent_id, str(ex)))
# Save the session state
self.torrentmanager.save_state()
if errors:
- log.warning('Failed to remove %d of %d torrents.', len(errors), len(torrent_ids))
+ log.warning(
+ 'Failed to remove %d of %d torrents.', len(errors), len(torrent_ids)
+ )
return errors
+
return task.deferLater(reactor, 0, do_remove_torrents)
@export
@@ -617,9 +655,7 @@ class Core(component.Component):
if key in DEPR_SESSION_STATUS_KEYS:
new_key = DEPR_SESSION_STATUS_KEYS[key]
log.debug(
- 'Deprecated session status key %s, please use %s',
- key,
- new_key,
+ 'Deprecated session status key %s, please use %s', key, new_key
)
status[key] = self.session_status[new_key]
else:
@@ -700,11 +736,22 @@ class Core(component.Component):
for torrent_id in torrent_ids:
self.resume_torrent(torrent_id)
- def create_torrent_status(self, torrent_id, torrent_keys, plugin_keys, diff=False, update=False, all_keys=False):
+ def create_torrent_status(
+ self,
+ torrent_id,
+ torrent_keys,
+ plugin_keys,
+ diff=False,
+ update=False,
+ all_keys=False,
+ ):
try:
- status = self.torrentmanager[torrent_id].get_status(torrent_keys, diff, update=update, all_keys=all_keys)
+ status = self.torrentmanager[torrent_id].get_status(
+ torrent_keys, diff, update=update, all_keys=all_keys
+ )
except KeyError:
import traceback
+
traceback.print_exc()
# Torrent was probaly removed meanwhile
return {}
@@ -716,9 +763,15 @@ 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])
+ 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,
+ torrent_id,
+ torrent_keys,
+ plugin_keys,
+ diff=diff,
+ update=True,
all_keys=not keys,
)
@@ -735,8 +788,11 @@ class Core(component.Component):
# Ask the plugin manager to fill in the plugin keys
if len(plugin_keys) > 0:
for key in status_dict:
- status_dict[key].update(self.pluginmanager.get_status(key, plugin_keys))
+ status_dict[key].update(
+ self.pluginmanager.get_status(key, plugin_keys)
+ )
return status_dict
+
d.addCallback(add_plugin_fields)
return d
@@ -798,7 +854,9 @@ class Core(component.Component):
settings = self.session.get_settings()
proxy_type = settings['proxy_type']
- proxy_hostname = settings['i2p_hostname'] if proxy_type == 6 else settings['proxy_hostname']
+ proxy_hostname = (
+ settings['i2p_hostname'] if proxy_type == 6 else settings['proxy_hostname']
+ )
proxy_port = settings['i2p_port'] if proxy_type == 6 else settings['proxy_port']
proxy_dict = {
'type': proxy_type,
@@ -939,8 +997,17 @@ class Core(component.Component):
@export
def create_torrent(
- self, path, tracker, piece_length, comment, target,
- webseeds, private, created_by, trackers, add_to_session,
+ self,
+ path,
+ tracker,
+ piece_length,
+ comment,
+ target,
+ webseeds,
+ private,
+ created_by,
+ trackers,
+ add_to_session,
):
log.debug('creating torrent..')
@@ -961,10 +1028,20 @@ class Core(component.Component):
).start()
def _create_torrent_thread(
- self, path, tracker, piece_length, comment, target,
- webseeds, private, created_by, trackers, add_to_session,
+ self,
+ path,
+ tracker,
+ piece_length,
+ comment,
+ target,
+ webseeds,
+ private,
+ created_by,
+ trackers,
+ add_to_session,
):
from deluge import metafile
+
metafile.make_meta_file(
path,
tracker,
@@ -1058,7 +1135,9 @@ class Core(component.Component):
def queue_top(self, torrent_ids):
log.debug('Attempting to queue %s to top', torrent_ids)
# torrent_ids must be sorted in reverse before moving to preserve order
- for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position, reverse=True):
+ for torrent_id in sorted(
+ torrent_ids, key=self.torrentmanager.get_queue_position, reverse=True
+ ):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_top(torrent_id):
@@ -1069,7 +1148,10 @@ class Core(component.Component):
@export
def queue_up(self, torrent_ids):
log.debug('Attempting to queue %s to up', torrent_ids)
- torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
+ torrents = (
+ (self.torrentmanager.get_queue_position(torrent_id), torrent_id)
+ for torrent_id in torrent_ids
+ )
torrent_moved = True
prev_queue_position = None
# torrent_ids must be sorted before moving.
@@ -1079,7 +1161,9 @@ class Core(component.Component):
try:
torrent_moved = self.torrentmanager.queue_up(torrent_id)
except KeyError:
- log.warning('torrent_id: %s does not exist in the queue', torrent_id)
+ log.warning(
+ 'torrent_id: %s does not exist in the queue', torrent_id
+ )
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get('EventManager').emit(TorrentQueueChangedEvent())
@@ -1089,7 +1173,10 @@ class Core(component.Component):
@export
def queue_down(self, torrent_ids):
log.debug('Attempting to queue %s to down', torrent_ids)
- torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
+ torrents = (
+ (self.torrentmanager.get_queue_position(torrent_id), torrent_id)
+ for torrent_id in torrent_ids
+ )
torrent_moved = True
prev_queue_position = None
# torrent_ids must be sorted before moving.
@@ -1099,7 +1186,9 @@ class Core(component.Component):
try:
torrent_moved = self.torrentmanager.queue_down(torrent_id)
except KeyError:
- log.warning('torrent_id: %s does not exist in the queue', torrent_id)
+ log.warning(
+ 'torrent_id: %s does not exist in the queue', torrent_id
+ )
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get('EventManager').emit(TorrentQueueChangedEvent())
@@ -1110,7 +1199,9 @@ class Core(component.Component):
def queue_bottom(self, torrent_ids):
log.debug('Attempting to queue %s to bottom', torrent_ids)
# torrent_ids must be sorted before moving to preserve order
- for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position):
+ for torrent_id in sorted(
+ torrent_ids, key=self.torrentmanager.get_queue_position
+ ):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_bottom(torrent_id):
diff --git a/deluge/core/daemon.py b/deluge/core/daemon.py
index bd203d940..42f39a23c 100644
--- a/deluge/core/daemon.py
+++ b/deluge/core/daemon.py
@@ -66,7 +66,12 @@ class Daemon(object):
"""The Deluge Daemon class"""
def __init__(
- self, listen_interface=None, outgoing_interface=None, interface=None, port=None, standalone=False,
+ self,
+ listen_interface=None,
+ outgoing_interface=None,
+ interface=None,
+ port=None,
+ standalone=False,
read_only_config_keys=None,
):
"""
@@ -84,19 +89,23 @@ class Daemon(object):
self.pid_file = get_config_dir('deluged.pid')
log.info('Deluge daemon %s', get_version())
if is_daemon_running(self.pid_file):
- raise DaemonRunningError('Deluge daemon already running with this config directory!')
+ raise DaemonRunningError(
+ 'Deluge daemon already running with this config directory!'
+ )
# Twisted catches signals to terminate, so just have it call the shutdown method.
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
# Catch some Windows specific signals
if windows_check():
+
def win_handler(ctrl_type):
"""Handle the Windows shutdown or close events."""
log.debug('windows handler ctrl_type: %s', ctrl_type)
if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
self._shutdown()
return 1
+
SetConsoleCtrlHandler(win_handler)
# Start the core as a thread and join it until it's done
@@ -123,7 +132,10 @@ class Daemon(object):
log.debug(
'Listening to UI on: %s:%s and bittorrent on: %s Making connections out on: %s',
- interface, port, listen_interface, outgoing_interface,
+ interface,
+ port,
+ listen_interface,
+ outgoing_interface,
)
def start(self):
@@ -179,4 +191,6 @@ class Daemon(object):
if rpc not in self.get_method_list():
return False
- return self.rpcserver.get_session_auth_level() >= self.rpcserver.get_rpc_auth_level(rpc)
+ return self.rpcserver.get_session_auth_level() >= self.rpcserver.get_rpc_auth_level(
+ rpc
+ )
diff --git a/deluge/core/daemon_entry.py b/deluge/core/daemon_entry.py
index eee14b32e..fffc8c8c2 100644
--- a/deluge/core/daemon_entry.py
+++ b/deluge/core/daemon_entry.py
@@ -24,15 +24,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',
+ '-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,
+ '-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',
+ '-i',
+ '--interface',
+ metavar='<ip-addr>',
+ dest='listen_interface',
+ action='store',
help=_('IP address to listen for BitTorrent connections'),
)
group.add_argument(
@@ -44,8 +55,12 @@ def add_daemon_options(parser):
help=_('The interface adapter name 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='',
+ '--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()
@@ -71,11 +86,12 @@ def start_daemon(skip_start=False):
# Check for any daemons running with this same config
from deluge.core.daemon import is_daemon_running
+
pid_file = get_config_dir('deluged.pid')
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,
+ 'If you believe this is an error, force starting by deleting: %s' % pid_file
)
sys.exit(1)
@@ -90,6 +106,7 @@ 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,
@@ -105,7 +122,8 @@ def start_daemon(skip_start=False):
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,
+ ex.interface,
+ ex.port,
)
sys.exit(1)
except Exception as ex:
@@ -118,4 +136,6 @@ def start_daemon(skip_start=False):
if options.pidfile:
os.remove(options.pidfile)
- return run_profiled(run_daemon, options, output_file=options.profile, do_profile=options.profile)
+ return run_profiled(
+ run_daemon, options, output_file=options.profile, do_profile=options.profile
+ )
diff --git a/deluge/core/eventmanager.py b/deluge/core/eventmanager.py
index 03efb5abb..5ba2989f9 100644
--- a/deluge/core/eventmanager.py
+++ b/deluge/core/eventmanager.py
@@ -36,7 +36,12 @@ class EventManager(component.Component):
try:
handler(*event.args)
except Exception as ex:
- log.error('Event handler %s failed in %s with exception %s', event.name, handler, ex)
+ log.error(
+ 'Event handler %s failed in %s with exception %s',
+ event.name,
+ handler,
+ ex,
+ )
def register_event_handler(self, event, handler):
"""
diff --git a/deluge/core/filtermanager.py b/deluge/core/filtermanager.py
index 34ba1d35f..82ded3268 100644
--- a/deluge/core/filtermanager.py
+++ b/deluge/core/filtermanager.py
@@ -101,6 +101,7 @@ class FilterManager(component.Component):
"""FilterManager
"""
+
def __init__(self, core):
component.Component.__init__(self, 'FilterManager')
log.debug('FilterManager init..')
@@ -115,12 +116,14 @@ class FilterManager(component.Component):
def _init_tracker_tree():
return {'Error': 0}
+
self.register_tree_field('tracker_host', _init_tracker_tree)
self.register_filter('tracker_host', tracker_error_filter)
def _init_users_tree():
return {'': 0}
+
self.register_tree_field('owner', _init_users_tree)
def filter_torrent_ids(self, filter_dict):
@@ -165,16 +168,22 @@ class FilterManager(component.Component):
for field, values in list(filter_dict.items()):
if field in self.registered_filters:
# Filters out doubles
- torrent_ids = list(set(self.registered_filters[field](torrent_ids, values)))
+ torrent_ids = list(
+ set(self.registered_filters[field](torrent_ids, values))
+ )
del filter_dict[field]
if not filter_dict:
return torrent_ids
- torrent_keys, plugin_keys = self.torrents.separate_keys(list(filter_dict), torrent_ids)
+ torrent_keys, plugin_keys = self.torrents.separate_keys(
+ list(filter_dict), torrent_ids
+ )
# Leftover filter arguments, default filter on status fields.
for torrent_id in list(torrent_ids):
- status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys)
+ status = self.core.create_torrent_status(
+ torrent_id, torrent_keys, plugin_keys
+ )
for field, values in filter_dict.items():
if field in status and status[field] in values:
continue
@@ -197,14 +206,18 @@ class FilterManager(component.Component):
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}
+ status = self.core.create_torrent_status(
+ torrent_id, torrent_keys, plugin_keys
+ ) # status={key:value}
for field in tree_keys:
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
if 'tracker_host' in items:
items['tracker_host']['All'] = len(torrent_ids)
- items['tracker_host']['Error'] = len(tracker_error_filter(torrent_ids, ('Error',)))
+ items['tracker_host']['Error'] = len(
+ tracker_error_filter(torrent_ids, ('Error',))
+ )
if not show_zero_hits:
for cat in ['state', 'owner', 'tracker_host']:
@@ -224,7 +237,9 @@ class FilterManager(component.Component):
init_state['All'] = len(self.torrents.get_torrent_list())
for state in TORRENT_STATE:
init_state[state] = 0
- init_state['Active'] = len(self.filter_state_active(self.torrents.get_torrent_list()))
+ init_state['Active'] = len(
+ self.filter_state_active(self.torrents.get_torrent_list())
+ )
return init_state
def register_filter(self, filter_id, filter_func, filter_value=None):
@@ -242,7 +257,9 @@ class FilterManager(component.Component):
def filter_state_active(self, torrent_ids):
for torrent_id in list(torrent_ids):
- status = self.torrents[torrent_id].get_status(['download_payload_rate', 'upload_payload_rate'])
+ status = self.torrents[torrent_id].get_status(
+ ['download_payload_rate', 'upload_payload_rate']
+ )
if status['download_payload_rate'] or status['upload_payload_rate']:
pass
else:
diff --git a/deluge/core/pluginmanager.py b/deluge/core/pluginmanager.py
index 0f5f14ec8..7d2f3a1e8 100644
--- a/deluge/core/pluginmanager.py
+++ b/deluge/core/pluginmanager.py
@@ -33,7 +33,7 @@ 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):
@@ -77,6 +77,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
if name not in self.plugins:
component.get('EventManager').emit(PluginDisabledEvent(name))
return result
+
d.addBoth(on_disable_plugin)
return d
diff --git a/deluge/core/preferencesmanager.py b/deluge/core/preferencesmanager.py
index 101360059..5d10b31ec 100644
--- a/deluge/core/preferencesmanager.py
+++ b/deluge/core/preferencesmanager.py
@@ -73,8 +73,9 @@ DEFAULT_PREFS = {
'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
+ 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,
@@ -134,7 +135,9 @@ class PreferencesManager(component.Component):
component.Component.__init__(self, 'PreferencesManager')
self.config = deluge.configmanager.ConfigManager('core.conf', DEFAULT_PREFS)
if 'proxies' in self.config:
- log.warning('Updating config file for proxy, using "peer" values to fill new "proxy" setting')
+ log.warning(
+ 'Updating config file for proxy, using "peer" values to fill new "proxy" setting'
+ )
self.config['proxy'].update(self.config['proxies']['peer'])
log.warning('New proxy config is: %s', self.config['proxy'])
del self.config['proxies']
@@ -205,7 +208,9 @@ class PreferencesManager(component.Component):
if self.config['random_port']:
if not self.config['listen_random_port']:
self.config['listen_random_port'] = random.randrange(49152, 65525)
- listen_ports = [self.config['listen_random_port']] * 2 # use single port range
+ listen_ports = [
+ self.config['listen_random_port']
+ ] * 2 # use single port range
else:
self.config['listen_random_port'] = None
listen_ports = self.config['listen_ports']
@@ -217,7 +222,9 @@ class PreferencesManager(component.Component):
log.debug(
'Listen Interface: %s, Ports: %s with use_sys_port: %s',
- interface, listen_ports, self.config['listen_use_sys_port'],
+ interface,
+ listen_ports,
+ self.config['listen_use_sys_port'],
)
interfaces = [
'%s:%s' % (interface, port)
@@ -227,7 +234,7 @@ class PreferencesManager(component.Component):
{
'listen_system_port_fallback': self.config['listen_use_sys_port'],
'listen_interfaces': ''.join(interfaces),
- },
+ }
)
def _on_set_outgoing_ports(self, key, value):
@@ -237,14 +244,22 @@ class PreferencesManager(component.Component):
self.__set_outgoing_ports()
def __set_outgoing_ports(self):
- port = 0 if self.config['random_outgoing_ports'] else self.config['outgoing_ports'][0]
+ port = (
+ 0
+ if self.config['random_outgoing_ports']
+ else self.config['outgoing_ports'][0]
+ )
if port:
- num_ports = self.config['outgoing_ports'][1] - self.config['outgoing_ports'][0]
+ num_ports = (
+ self.config['outgoing_ports'][1] - self.config['outgoing_ports'][0]
+ )
num_ports = num_ports if num_ports > 1 else 5
else:
num_ports = 0
log.debug('Outgoing port set to %s with range: %s', port, num_ports)
- self.core.apply_session_settings({'outgoing_port': port, 'num_outgoing_ports': num_ports})
+ self.core.apply_session_settings(
+ {'outgoing_port': port, 'num_outgoing_ports': num_ports}
+ )
def _on_set_peer_tos(self, key, value):
try:
@@ -263,12 +278,11 @@ 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}
)
- self.core.apply_session_settings({
- 'dht_bootstrap_nodes': ','.join(dht_bootstraps),
- 'enable_dht': value,
- })
def _on_set_upnp(self, key, value):
self.core.apply_session_setting('enable_upnp', value)
@@ -294,14 +308,20 @@ class PreferencesManager(component.Component):
def _on_set_encryption(self, key, value):
# 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}
+ 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']]),
+ '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):
@@ -364,20 +384,29 @@ class PreferencesManager(component.Component):
def run(self):
import time
+
now = time.time()
# check if we've done this within the last week or never
if (now - self.config['info_sent']) >= (60 * 60 * 24 * 7):
try:
- url = 'http://deluge-torrent.org/stats_get.php?processor=' + \
- platform.machine() + '&python=' + platform.python_version() \
- + '&deluge=' + deluge.common.get_version() \
- + '&os=' + platform.system() \
- + '&plugins=' + quote_plus(':'.join(self.config['enabled_plugins']))
+ url = (
+ 'http://deluge-torrent.org/stats_get.php?processor='
+ + platform.machine()
+ + '&python='
+ + platform.python_version()
+ + '&deluge='
+ + deluge.common.get_version()
+ + '&os='
+ + platform.system()
+ + '&plugins='
+ + quote_plus(':'.join(self.config['enabled_plugins']))
+ )
urlopen(url)
except IOError as ex:
log.debug('Network error while trying to send info: %s', ex)
else:
self.config['info_sent'] = now
+
if value:
SendInfoThread(self.config).start()
@@ -389,7 +418,7 @@ 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:
@@ -410,20 +439,23 @@ class PreferencesManager(component.Component):
}
if value['type'] == lt.proxy_type.i2p_proxy:
- proxy_settings.update({
- 'proxy_type': lt.proxy_type.i2p_proxy,
- 'i2p_hostname': value['hostname'],
- 'i2p_port': value['port'],
- })
+ proxy_settings.update(
+ {
+ 'proxy_type': lt.proxy_type.i2p_proxy,
+ 'i2p_hostname': value['hostname'],
+ 'i2p_port': value['port'],
+ }
+ )
elif value['type'] != lt.proxy_type.none:
- proxy_settings.update({
- 'proxy_type': value['type'],
- 'proxy_hostname': value['hostname'],
- 'proxy_port': value['port'],
- 'proxy_username': value['username'],
- 'proxy_password': value['password'],
-
- })
+ proxy_settings.update(
+ {
+ 'proxy_type': value['type'],
+ 'proxy_hostname': value['hostname'],
+ 'proxy_port': value['port'],
+ 'proxy_username': value['username'],
+ 'proxy_password': value['password'],
+ }
+ )
self.core.apply_session_settings(proxy_settings)
@@ -434,7 +466,9 @@ class PreferencesManager(component.Component):
# Load the GeoIP DB for country look-ups if available
if os.path.exists(geoipdb_path):
try:
- self.core.geoip_instance = GeoIP.open(geoipdb_path, GeoIP.GEOIP_STANDARD)
+ self.core.geoip_instance = GeoIP.open(
+ geoipdb_path, GeoIP.GEOIP_STANDARD
+ )
except AttributeError:
log.warning('GeoIP Unavailable')
else:
diff --git a/deluge/core/rpcserver.py b/deluge/core/rpcserver.py
index 146f39c3e..07e6f1531 100644
--- a/deluge/core/rpcserver.py
+++ b/deluge/core/rpcserver.py
@@ -24,9 +24,19 @@ from twisted.internet.protocol import Factory, connectionDone
import deluge.component as component
import deluge.configmanager
-from deluge.core.authmanager import AUTH_LEVEL_ADMIN, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_NONE
+from deluge.core.authmanager import (
+ AUTH_LEVEL_ADMIN,
+ AUTH_LEVEL_DEFAULT,
+ AUTH_LEVEL_NONE,
+)
from deluge.crypto_utils import get_context_factory
-from deluge.error import DelugeError, IncompatibleClient, NotAuthorizedError, WrappedException, _ClientSideRecreateError
+from deluge.error import (
+ DelugeError,
+ IncompatibleClient,
+ NotAuthorizedError,
+ WrappedException,
+ _ClientSideRecreateError,
+)
from deluge.event import ClientDisconnectedEvent
from deluge.transfer import DelugeTransferProtocol
@@ -48,6 +58,7 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
:type auth_level: int
"""
+
def wrap(func, *args, **kwargs):
func._rpcserver_export = True
func._rpcserver_auth_level = auth_level
@@ -120,8 +131,8 @@ 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),
+ 'Received invalid rpc request: number of items ' 'in request is %s',
+ len(call),
)
continue
# log.debug('RPCRequest: %s', format_request(call))
@@ -148,14 +159,11 @@ 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.factory.authorized_sessions[self.transport.sessionno] = self.AuthLevel(
+ AUTH_LEVEL_NONE, ''
+ )
def connectionLost(self, reason=connectionDone): # NOQA: N802
"""
@@ -174,7 +182,9 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
del self.factory.interested_events[self.transport.sessionno]
if self.factory.state == 'running':
- component.get('EventManager').emit(ClientDisconnectedEvent(self.factory.session_id))
+ component.get('EventManager').emit(
+ ClientDisconnectedEvent(self.factory.session_id)
+ )
log.info('Deluge client disconnected: %s', reason.value)
def valid_session(self):
@@ -196,6 +206,7 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
:type kwargs: dict
"""
+
def send_error():
"""
Sends an error response with the contents of the exception that was raised.
@@ -203,29 +214,34 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
exc_type, exc_value, dummy_exc_trace = sys.exc_info()
formated_tb = traceback.format_exc()
try:
- self.sendData((
- RPC_ERROR,
- request_id,
- exc_type.__name__,
- exc_value._args,
- exc_value._kwargs,
- formated_tb,
- ))
+ self.sendData(
+ (
+ RPC_ERROR,
+ request_id,
+ exc_type.__name__,
+ exc_value._args,
+ exc_value._kwargs,
+ 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,
+ '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:
- log.error('An exception occurred while sending RPC_ERROR to client: %s', ex)
+ log.error(
+ 'An exception occurred while sending RPC_ERROR to client: %s', ex
+ )
if method == 'daemon.info':
# This is a special case and used in the initial connection process
@@ -285,7 +301,9 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
log.debug('RPC dispatch %s', method)
try:
method_auth_requirement = self.factory.methods[method]._rpcserver_auth_level
- auth_level = self.factory.authorized_sessions[self.transport.sessionno].auth_level
+ 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(
@@ -307,6 +325,7 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
# Check if the return value is a deferred, since we'll need to
# wait for it to fire before sending the RPC_RESPONSE
if isinstance(ret, defer.Deferred):
+
def on_success(result):
try:
self.sendData((RPC_RESPONSE, request_id, result))
@@ -380,7 +399,9 @@ class RPCServer(component.Component):
pkey = os.path.join(deluge.configmanager.get_config_dir('ssl'), 'daemon.pkey')
try:
- reactor.listenSSL(port, self.factory, get_context_factory(cert, pkey), interface=hostname)
+ reactor.listenSSL(
+ port, self.factory, get_context_factory(cert, pkey), interface=hostname
+ )
except Exception as ex:
log.debug('Daemon already running or port not available.: %s', ex)
raise
@@ -513,7 +534,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):
@@ -526,22 +547,35 @@ class RPCServer(component.Component):
:type event: :class:`deluge.event.DelugeEvent`
"""
if not self.is_session_valid(session_id):
- log.debug('Session ID %s is not valid. Not sending event "%s".', session_id, event.name)
+ 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,
+ 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)
+ 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,
+ event.name,
+ event.args,
+ session_id,
+ )
+ self.factory.session_protocols[session_id].sendData(
+ (RPC_EVENT, event.name, event.args)
)
- self.factory.session_protocols[session_id].sendData((RPC_EVENT, event.name, event.args))
def stop(self):
self.factory.state = 'stopping'
@@ -568,6 +602,7 @@ def generate_ssl_keys():
This method generates a new SSL key/cert.
"""
from deluge.common import PY2
+
digest = 'sha256' if not PY2 else b'sha256'
# Generate key pair
diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py
index 2a834c773..7ff0091ff 100644
--- a/deluge/core/torrent.py
+++ b/deluge/core/torrent.py
@@ -28,7 +28,11 @@ from deluge.common import decode_bytes
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.decorators import deprecated
-from deluge.event import TorrentFolderRenamedEvent, TorrentStateChangedEvent, TorrentTrackerStatusEvent
+from deluge.event import (
+ TorrentFolderRenamedEvent,
+ TorrentStateChangedEvent,
+ TorrentTrackerStatusEvent,
+)
try:
from urllib.parse import urlparse
@@ -65,6 +69,7 @@ def sanitize_filepath(filepath, folder=False):
Args:
folder (bool): A trailing slash is appended to the returned filepath.
"""
+
def clean_filename(filename):
"""Strips whitespace and discards dotted filenames"""
filename = filename.strip()
@@ -110,12 +115,14 @@ def convert_lt_files(files):
except AttributeError:
file_path = _file.path
- filelist.append({
- 'index': index,
- 'path': file_path.replace('\\', '/'),
- 'size': _file.size,
- 'offset': _file.offset,
- })
+ filelist.append(
+ {
+ 'index': index,
+ 'path': file_path.replace('\\', '/'),
+ 'size': _file.size,
+ 'offset': _file.offset,
+ }
+ )
return filelist
@@ -152,6 +159,7 @@ class TorrentOptions(dict):
stop_ratio (float): The seeding ratio to stop (or remove) the torrent at.
super_seeding (bool): Enable super seeding/initial seeding.
"""
+
def __init__(self):
super(TorrentOptions, self).__init__()
config = ConfigManager('core.conf').config
@@ -227,6 +235,7 @@ class Torrent(object):
we can re-pause it after its done if necessary
forced_error (TorrentError): Keep track if we have forced this torrent to be in Error state.
"""
+
def __init__(self, handle, options, state=None, filename=None, magnet=None):
self.torrent_id = str(handle.info_hash())
if log.isEnabledFor(logging.DEBUG):
@@ -295,7 +304,9 @@ class Torrent(object):
# Skip set_prioritize_first_last if set_file_priorities is in options as it also calls the method.
if 'file_priorities' in options and 'prioritize_first_last_pieces' in options:
- self.options['prioritize_first_last_pieces'] = options.pop('prioritize_first_last_pieces')
+ self.options['prioritize_first_last_pieces'] = options.pop(
+ 'prioritize_first_last_pieces'
+ )
for key, value in options.items():
if key in self.options:
@@ -407,8 +418,12 @@ class Torrent(object):
# Set the pieces in first and last ranges to priority 7
# if they are not marked as do not download
- priorities[first_start:first_end] = [p and 7 for p in priorities[first_start:first_end]]
- priorities[last_start:last_end] = [p and 7 for p in priorities[last_start:last_end]]
+ priorities[first_start:first_end] = [
+ p and 7 for p in priorities[first_start:first_end]
+ ]
+ priorities[last_start:last_end] = [
+ p and 7 for p in priorities[last_start:last_end]
+ ]
# Setting the priorites for all the pieces of this torrent
self.handle.prioritize_pieces(priorities)
@@ -494,10 +509,15 @@ class Torrent(object):
"""
if log.isEnabledFor(logging.DEBUG):
- log.debug('Setting %s file priorities to: %s', self.torrent_id, file_priorities)
+ log.debug(
+ 'Setting %s file priorities to: %s', self.torrent_id, file_priorities
+ )
- if (self.handle.has_metadata() and file_priorities and
- len(file_priorities) == len(self.get_files())):
+ if (
+ self.handle.has_metadata()
+ and file_priorities
+ and len(file_priorities) == len(self.get_files())
+ ):
self.handle.prioritize_files(file_priorities)
else:
log.debug('Unable to set new file priorities.')
@@ -516,7 +536,9 @@ class Torrent(object):
# Set the first/last priorities if needed.
if self.options['prioritize_first_last_pieces']:
- self.set_prioritize_first_last_pieces(self.options['prioritize_first_last_pieces'])
+ self.set_prioritize_first_last_pieces(
+ self.options['prioritize_first_last_pieces']
+ )
@deprecated
def set_save_path(self, download_location):
@@ -592,11 +614,16 @@ class Torrent(object):
if self.tracker_status != status:
self.tracker_status = status
- component.get('EventManager').emit(TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status))
+ component.get('EventManager').emit(
+ TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status)
+ )
def merge_trackers(self, torrent_info):
"""Merges new trackers in torrent_info into torrent"""
- log.info('Adding any new trackers to torrent (%s) already in session...', self.torrent_id)
+ log.info(
+ 'Adding any new trackers to torrent (%s) already in session...',
+ self.torrent_id,
+ )
if not torrent_info:
return
# Don't merge trackers if either torrent has private flag set.
@@ -634,15 +661,23 @@ class Torrent(object):
self.state = LT_TORRENT_STATE_MAP.get(str(status.state), str(status.state))
if self.state != old_state:
- component.get('EventManager').emit(TorrentStateChangedEvent(self.torrent_id, self.state))
+ component.get('EventManager').emit(
+ TorrentStateChangedEvent(self.torrent_id, self.state)
+ )
if log.isEnabledFor(logging.DEBUG):
log.debug(
'State from lt was: %s | Session is paused: %s\nTorrent state set from "%s" to "%s" (%s)',
- 'error' if status_error else status.state, session_paused, old_state, self.state, self.torrent_id,
+ 'error' if status_error else status.state,
+ session_paused,
+ old_state,
+ self.state,
+ self.torrent_id,
)
if self.forced_error:
- log.debug('Torrent Error state message: %s', self.forced_error.error_message)
+ log.debug(
+ 'Torrent Error state message: %s', self.forced_error.error_message
+ )
def set_status_message(self, message=None):
"""Sets the torrent status message.
@@ -783,24 +818,30 @@ class Torrent(object):
client = decode_bytes(peer.client)
try:
- country = component.get('Core').geoip_instance.country_code_by_addr(peer.ip[0])
+ country = component.get('Core').geoip_instance.country_code_by_addr(
+ peer.ip[0]
+ )
except AttributeError:
country = ''
else:
try:
- country = ''.join([char if char.isalpha() else ' ' for char in country])
+ country = ''.join(
+ [char if char.isalpha() else ' ' for char in country]
+ )
except TypeError:
country = ''
- ret.append({
- 'client': client,
- 'country': country,
- 'down_speed': peer.payload_down_speed,
- 'ip': '%s:%s' % (peer.ip[0], peer.ip[1]),
- 'progress': peer.progress,
- 'seed': peer.flags & peer.seed,
- 'up_speed': peer.payload_up_speed,
- })
+ ret.append(
+ {
+ 'client': client,
+ 'country': country,
+ 'down_speed': peer.payload_down_speed,
+ 'ip': '%s:%s' % (peer.ip[0], peer.ip[1]),
+ 'progress': peer.progress,
+ 'seed': peer.flags & peer.seed,
+ 'up_speed': peer.payload_up_speed,
+ }
+ )
return ret
@@ -832,8 +873,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())
+ 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):
@@ -854,7 +897,7 @@ class Torrent(object):
if tracker:
url = urlparse(tracker.replace('udp://', 'http://'))
if hasattr(url, 'hostname'):
- host = (url.hostname or 'DHT')
+ host = url.hostname or 'DHT'
# Check if hostname is an IP address and just return it if that's the case
try:
socket.inet_aton(host)
@@ -995,7 +1038,9 @@ class Torrent(object):
'seeding_time': lambda: self.status.seeding_time,
'finished_time': lambda: self.status.finished_time,
'all_time_download': lambda: self.status.all_time_download,
- 'storage_mode': lambda: self.status.storage_mode.name.split('_')[2], # sparse or allocate
+ 'storage_mode': lambda: self.status.storage_mode.name.split('_')[
+ 2
+ ], # sparse or allocate
'distributed_copies': lambda: max(0.0, self.status.distributed_copies),
'download_payload_rate': lambda: self.status.download_payload_rate,
'file_priorities': self.get_file_priorities,
@@ -1008,8 +1053,12 @@ class Torrent(object):
'max_upload_slots': lambda: self.options['max_upload_slots'],
'max_upload_speed': lambda: self.options['max_upload_speed'],
'message': lambda: self.statusmsg,
- 'move_on_completed_path': lambda: self.options['move_completed_path'], # Deprecated: move_completed_path
- 'move_on_completed': lambda: self.options['move_completed'], # Deprecated: Use move_completed
+ 'move_on_completed_path': lambda: self.options[
+ 'move_completed_path'
+ ], # Deprecated: move_completed_path
+ 'move_on_completed': lambda: self.options[
+ 'move_completed'
+ ], # Deprecated: Use move_completed
'move_completed_path': lambda: self.options['move_completed_path'],
'move_completed': lambda: self.options['move_completed'],
'next_announce': lambda: self.status.next_announce.seconds,
@@ -1017,16 +1066,24 @@ class Torrent(object):
'num_seeds': lambda: self.status.num_seeds,
'owner': lambda: self.options['owner'],
'paused': lambda: self.status.paused,
- 'prioritize_first_last': lambda: self.options['prioritize_first_last_pieces'],
+ 'prioritize_first_last': lambda: self.options[
+ 'prioritize_first_last_pieces'
+ ],
# Deprecated: Use prioritize_first_last_pieces
- 'prioritize_first_last_pieces': lambda: self.options['prioritize_first_last_pieces'],
+ 'prioritize_first_last_pieces': lambda: self.options[
+ 'prioritize_first_last_pieces'
+ ],
'sequential_download': lambda: self.options['sequential_download'],
'progress': self.get_progress,
'shared': lambda: self.options['shared'],
'remove_at_ratio': lambda: self.options['remove_at_ratio'],
- 'save_path': lambda: self.options['download_location'], # Deprecated: Use download_location
+ '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
+ 'seeds_peers_ratio': lambda: -1.0
+ if self.status.num_incomplete == 0
+ else ( # Use -1.0 to signify infinity
self.status.num_complete / self.status.num_incomplete
),
'seed_rank': lambda: self.status.seed_rank,
@@ -1041,19 +1098,32 @@ class Torrent(object):
'total_seeds': lambda: self.status.num_complete,
'total_uploaded': lambda: self.status.all_time_upload,
'total_wanted': lambda: self.status.total_wanted,
- 'total_remaining': lambda: self.status.total_wanted - self.status.total_wanted_done,
+ 'total_remaining': lambda: self.status.total_wanted
+ - self.status.total_wanted_done,
'tracker': lambda: self.status.current_tracker,
'tracker_host': self.get_tracker_host,
'trackers': lambda: self.trackers,
'tracker_status': lambda: self.tracker_status,
'upload_payload_rate': lambda: self.status.upload_payload_rate,
- 'comment': lambda: decode_bytes(self.torrent_info.comment()) if self.has_metadata else '',
- 'creator': lambda: decode_bytes(self.torrent_info.creator()) if self.has_metadata else '',
- 'num_files': lambda: self.torrent_info.num_files() if self.has_metadata else 0,
- 'num_pieces': lambda: self.torrent_info.num_pieces() if self.has_metadata else 0,
- 'piece_length': lambda: self.torrent_info.piece_length() if self.has_metadata else 0,
+ 'comment': lambda: decode_bytes(self.torrent_info.comment())
+ if self.has_metadata
+ else '',
+ 'creator': lambda: decode_bytes(self.torrent_info.creator())
+ if self.has_metadata
+ else '',
+ 'num_files': lambda: self.torrent_info.num_files()
+ if self.has_metadata
+ else 0,
+ 'num_pieces': lambda: self.torrent_info.num_pieces()
+ if self.has_metadata
+ else 0,
+ 'piece_length': lambda: self.torrent_info.piece_length()
+ if self.has_metadata
+ else 0,
'private': lambda: self.torrent_info.priv() if self.has_metadata else False,
- 'total_size': lambda: self.torrent_info.total_size() if self.has_metadata else 0,
+ 'total_size': lambda: self.torrent_info.total_size()
+ if self.has_metadata
+ else 0,
'eta': self.get_eta,
'file_progress': self.get_file_progress,
'files': self.get_files,
@@ -1090,7 +1160,9 @@ class Torrent(object):
# show it as 'Paused'. We need to emit a torrent_paused signal because
# the torrent_paused alert from libtorrent will not be generated.
self.update_state()
- component.get('EventManager').emit(TorrentStateChangedEvent(self.torrent_id, 'Paused'))
+ component.get('EventManager').emit(
+ TorrentStateChangedEvent(self.torrent_id, 'Paused')
+ )
else:
try:
self.handle.pause()
@@ -1102,9 +1174,14 @@ class Torrent(object):
if self.status.paused and self.status.auto_managed:
log.debug('Resume not possible for auto-managed torrent!')
elif self.forced_error and self.forced_error.was_paused:
- log.debug('Resume skipped for forced_error torrent as it was originally paused.')
- elif (self.status.is_finished and self.options['stop_at_ratio'] and
- self.get_ratio() >= self.options['stop_ratio']):
+ log.debug(
+ 'Resume skipped for forced_error torrent as it was originally paused.'
+ )
+ elif (
+ self.status.is_finished
+ and self.options['stop_at_ratio']
+ and self.get_ratio() >= self.options['stop_ratio']
+ ):
log.debug('Resume skipped for torrent as it has reached "stop_seed_ratio".')
else:
# Check if torrent was originally being auto-managed.
@@ -1157,7 +1234,9 @@ class Torrent(object):
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,
+ self.torrent_id,
+ dest,
+ ex,
)
return False
@@ -1191,9 +1270,9 @@ class Torrent(object):
flags = lt.save_resume_flags_t.flush_disk_cache if flush_disk_cache else 0
# Don't generate fastresume data if torrent is in a Deluge Error state.
if self.forced_error:
- component.get('TorrentManager').waiting_on_resume_data[self.torrent_id].errback(
- UserWarning('Skipped creating resume_data while in Error state'),
- )
+ component.get('TorrentManager').waiting_on_resume_data[
+ self.torrent_id
+ ].errback(UserWarning('Skipped creating resume_data while in Error state'))
else:
self.handle.save_resume_data(flags)
@@ -1232,9 +1311,13 @@ class Torrent(object):
def delete_torrentfile(self, delete_copies=False):
"""Deletes the .torrent file in the state directory in config"""
- torrent_files = [os.path.join(get_config_dir(), 'state', self.torrent_id + '.torrent')]
+ torrent_files = [
+ os.path.join(get_config_dir(), 'state', self.torrent_id + '.torrent')
+ ]
if delete_copies:
- torrent_files.append(os.path.join(self.config['torrentfiles_location'], self.filename))
+ torrent_files.append(
+ os.path.join(self.config['torrentfiles_location'], self.filename)
+ )
for torrent_file in torrent_files:
log.debug('Deleting torrent file: %s', torrent_file)
@@ -1325,7 +1408,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:
@@ -1335,10 +1418,14 @@ class Torrent(object):
def on_folder_rename_complete(dummy_result, torrent, folder, new_folder):
"""Folder rename complete"""
- component.get('EventManager').emit(TorrentFolderRenamedEvent(torrent.torrent_id, folder, new_folder))
+ component.get('EventManager').emit(
+ TorrentFolderRenamedEvent(torrent.torrent_id, folder, new_folder)
+ )
# Empty folders are removed after libtorrent folder renames
self.remove_empty_folders(folder)
- torrent.waiting_on_folder_rename = [_dir for _dir in torrent.waiting_on_folder_rename if _dir]
+ torrent.waiting_on_folder_rename = [
+ _dir for _dir in torrent.waiting_on_folder_rename if _dir
+ ]
component.get('TorrentManager').save_resume_data((self.torrent_id,))
d = DeferredList(list(wait_on_folder.values()))
@@ -1355,7 +1442,9 @@ class Torrent(object):
"""
# Removes leading slashes that can cause join to ignore download_location
download_location = self.options['download_location']
- folder_full_path = os.path.normpath(os.path.join(download_location, folder.lstrip('\\/')))
+ folder_full_path = os.path.normpath(
+ os.path.join(download_location, folder.lstrip('\\/'))
+ )
try:
if not os.listdir(folder_full_path):
@@ -1366,7 +1455,9 @@ class Torrent(object):
for name in dirs:
try:
os.removedirs(os.path.join(root, name))
- log.debug('Removed Empty Folder %s', os.path.join(root, name))
+ log.debug(
+ 'Removed Empty Folder %s', os.path.join(root, name)
+ )
except OSError as ex:
log.debug(ex)
@@ -1389,16 +1480,24 @@ class Torrent(object):
pieces = None
else:
pieces = []
- for piece, avail_piece in zip(self.status.pieces, self.handle.piece_availability()):
+ for piece, avail_piece in zip(
+ self.status.pieces, self.handle.piece_availability()
+ ):
if piece:
pieces.append(3) # Completed.
elif avail_piece:
- pieces.append(1) # Available, just not downloaded nor being downloaded.
+ pieces.append(
+ 1
+ ) # Available, just not downloaded nor being downloaded.
else:
- pieces.append(0) # Missing, no known peer with piece, or not asked for yet.
+ pieces.append(
+ 0
+ ) # Missing, no known peer with piece, or not asked for yet.
for peer_info in self.handle.get_peer_info():
if peer_info.downloading_piece_index >= 0:
- pieces[peer_info.downloading_piece_index] = 2 # Being downloaded from peer.
+ pieces[
+ peer_info.downloading_piece_index
+ ] = 2 # Being downloaded from peer.
return pieces
diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py
index 8e221fe32..c3307e33f 100644
--- a/deluge/core/torrentmanager.py
+++ b/deluge/core/torrentmanager.py
@@ -29,17 +29,25 @@ from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
from deluge.error import AddTorrentError, InvalidTorrentError
-from deluge.event import (ExternalIPEvent, PreTorrentRemovedEvent, SessionStartedEvent, TorrentAddedEvent,
- TorrentFileCompletedEvent, TorrentFileRenamedEvent, TorrentFinishedEvent, TorrentRemovedEvent,
- TorrentResumedEvent)
+from deluge.event import (
+ ExternalIPEvent,
+ PreTorrentRemovedEvent,
+ SessionStartedEvent,
+ TorrentAddedEvent,
+ TorrentFileCompletedEvent,
+ TorrentFileRenamedEvent,
+ TorrentFinishedEvent,
+ TorrentRemovedEvent,
+ TorrentResumedEvent,
+)
log = logging.getLogger(__name__)
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_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
)
@@ -50,6 +58,7 @@ 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,
@@ -99,11 +108,14 @@ class TorrentManagerState: # pylint: disable=old-style-class
This must be old style class to avoid breaking torrent.state file.
"""
+
def __init__(self):
self.torrents = []
def __eq__(self, other):
- return isinstance(other, TorrentManagerState) and self.torrents == other.torrents
+ return (
+ isinstance(other, TorrentManagerState) and self.torrents == other.torrents
+ )
def __ne__(self, other):
return not self == other
@@ -115,11 +127,14 @@ class TorrentManager(component.Component):
This object is also responsible for saving the state of the session for use on restart.
"""
+
callLater = reactor.callLater
def __init__(self):
component.Component.__init__(
- self, 'TorrentManager', interval=5,
+ self,
+ 'TorrentManager',
+ interval=5,
depend=['CorePluginManager', 'AlertManager'],
)
log.debug('TorrentManager init...')
@@ -163,8 +178,10 @@ class TorrentManager(component.Component):
# 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',
+ '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:
@@ -173,18 +190,34 @@ class TorrentManager(component.Component):
# Register alert functions
alert_handles = [
- 'external_ip_alert', 'performance_alert', 'add_torrent_alert',
- 'metadata_received_alert', 'torrent_finished_alert', 'torrent_paused_alert',
- 'torrent_checked_alert', 'torrent_resumed_alert', 'tracker_reply_alert',
- 'tracker_announce_alert', 'tracker_warning_alert', 'tracker_error_alert',
- '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',
+ 'external_ip_alert',
+ 'performance_alert',
+ 'add_torrent_alert',
+ 'metadata_received_alert',
+ 'torrent_finished_alert',
+ 'torrent_paused_alert',
+ 'torrent_checked_alert',
+ 'torrent_resumed_alert',
+ 'tracker_reply_alert',
+ 'tracker_announce_alert',
+ 'tracker_warning_alert',
+ 'tracker_error_alert',
+ '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',
]
for alert_handle in alert_handles:
- on_alert_func = getattr(self, ''.join(['on_alert_', alert_handle.replace('_alert', '')]))
+ on_alert_func = getattr(
+ self, ''.join(['on_alert_', alert_handle.replace('_alert', '')])
+ )
self.alerts.register_handler(alert_handle, on_alert_func)
# Define timers
@@ -195,7 +228,9 @@ class TorrentManager(component.Component):
def start(self):
# Check for old temp file to verify safe shutdown
if os.path.isfile(self.temp_file):
- log.warning('Potential bad shutdown of Deluge detected, archiving torrent state files...')
+ log.warning(
+ 'Potential bad shutdown of Deluge detected, archiving torrent state files...'
+ )
arc_filepaths = []
for filename in ('torrents.fastresume', 'torrents.state'):
filepath = os.path.join(self.state_dir, filename)
@@ -240,14 +275,20 @@ 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
if not torrent.options['stop_at_ratio']:
continue
- if torrent.get_ratio() >= torrent.options['stop_ratio'] and torrent.is_finished:
+ if (
+ torrent.get_ratio() >= torrent.options['stop_ratio']
+ and torrent.is_finished
+ ):
if torrent.options['remove_at_ratio']:
self.remove(torrent_id)
break
@@ -324,11 +365,12 @@ class TorrentManager(component.Component):
add_torrent_params = {}
add_torrent_params['save_path'] = gettempdir()
add_torrent_params['url'] = magnet.strip().encode('utf8')
- 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_upload_mode
- )
+ 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_upload_mode
+ )
^ lt.add_torrent_params_flags_t.flag_auto_managed
^ lt.add_torrent_params_flags_t.flag_paused
)
@@ -379,7 +421,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 = {}
@@ -387,7 +429,9 @@ class TorrentManager(component.Component):
add_torrent_params['ti'] = torrent_info
name = torrent_info.name()
if not name:
- name = torrent_info.file_at(0).path.replace('\\', '/', 1).split('/', 1)[0]
+ name = (
+ torrent_info.file_at(0).path.replace('\\', '/', 1).split('/', 1)[0]
+ )
add_torrent_params['name'] = name
torrent_id = str(torrent_info.info_hash())
elif magnet:
@@ -397,7 +441,9 @@ class TorrentManager(component.Component):
add_torrent_params['name'] = magnet_info['name']
torrent_id = magnet_info['info_hash']
else:
- raise AddTorrentError('Unable to add magnet, invalid magnet info: %s' % magnet)
+ raise AddTorrentError(
+ 'Unable to add magnet, invalid magnet info: %s' % magnet
+ )
# Check for existing torrent in session.
if torrent_id in self.get_torrent_list():
@@ -437,13 +483,10 @@ class TorrentManager(component.Component):
# 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
- )
+ 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
@@ -480,17 +523,21 @@ class TorrentManager(component.Component):
"""
if not torrent_info and not filedump and not magnet:
- raise AddTorrentError('You must specify a valid torrent_info, torrent state or magnet.')
+ raise AddTorrentError(
+ 'You must specify a valid torrent_info, torrent state or magnet.'
+ )
if filedump:
try:
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except RuntimeError as ex:
- raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex)
+ raise AddTorrentError(
+ 'Unable to add torrent, decoding filedump failed: %s' % ex
+ )
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
@@ -506,7 +553,7 @@ 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
@@ -541,28 +588,51 @@ class TorrentManager(component.Component):
"""
if not torrent_info and not filedump and not magnet:
- raise AddTorrentError('You must specify a valid torrent_info, torrent state or magnet.')
+ raise AddTorrentError(
+ 'You must specify a valid torrent_info, torrent state or magnet.'
+ )
if filedump:
try:
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except RuntimeError as ex:
- raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex)
+ raise AddTorrentError(
+ 'Unable to add torrent, decoding filedump failed: %s' % ex
+ )
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)
+ self.torrents_loading[torrent_id] = (
+ d,
+ options,
+ state,
+ filename,
+ magnet,
+ resume_data,
+ filedump,
+ save_state,
+ )
try:
self.session.async_add_torrent(add_torrent_params)
except RuntimeError as ex:
raise AddTorrentError('Unable to add torrent to session: %s' % ex)
return d
- def _add_torrent_obj(self, handle, options, state, filename, magnet, resume_data, filedump, save_state):
+ def _add_torrent_obj(
+ self,
+ handle,
+ options,
+ state,
+ filename,
+ magnet,
+ resume_data,
+ filedump,
+ save_state,
+ ):
# For magnets added with metadata, filename is used so set as magnet.
if not magnet and is_magnet(filename):
magnet = filename
@@ -590,7 +660,9 @@ class TorrentManager(component.Component):
# Emit torrent_added signal.
from_state = state is not None
- component.get('EventManager').emit(TorrentAddedEvent(torrent.torrent_id, from_state))
+ component.get('EventManager').emit(
+ TorrentAddedEvent(torrent.torrent_id, from_state)
+ )
if log.isEnabledFor(logging.DEBUG):
log.debug('Torrent added: %s', str(handle.info_hash()))
@@ -614,10 +686,19 @@ 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)
@@ -661,7 +742,9 @@ class TorrentManager(component.Component):
self.resume_data.pop(torrent_id, None)
# Remove the .torrent file in the state and copy location, if user requested.
- delete_copies = self.config['copy_torrent_file'] and self.config['del_copy_torrent_file']
+ delete_copies = (
+ self.config['copy_torrent_file'] and self.config['del_copy_torrent_file']
+ )
torrent.delete_torrentfile(delete_copies)
# Remove from set if it wasn't finished
@@ -670,7 +753,9 @@ class TorrentManager(component.Component):
self.queued_torrents.remove(torrent_id)
except KeyError:
log.debug('%s is not in queued torrents set.', torrent_id)
- raise InvalidTorrentError('%s is not in queued torrents set.' % torrent_id)
+ raise InvalidTorrentError(
+ '%s is not in queued torrents set.' % torrent_id
+ )
# Remove the torrent from deluge's session
del self.torrents[torrent_id]
@@ -680,7 +765,11 @@ class TorrentManager(component.Component):
# Emit the signal to the clients
component.get('EventManager').emit(TorrentRemovedEvent(torrent_id))
- log.info('Torrent %s removed by user: %s', torrent_name, component.get('RPCServer').get_session_user())
+ log.info(
+ 'Torrent %s removed by user: %s',
+ torrent_name,
+ component.get('RPCServer').get_session_user(),
+ )
return True
def fixup_state(self, state):
@@ -701,7 +790,9 @@ class TorrentManager(component.Component):
for t_state in state.torrents:
setattr(t_state, attr, getattr(t_state_tmp, attr, None))
except AttributeError as ex:
- log.error('Unable to update state file to a compatible version: %s', ex)
+ log.error(
+ 'Unable to update state file to a compatible version: %s', ex
+ )
return state
def open_state(self):
@@ -740,7 +831,9 @@ class TorrentManager(component.Component):
state = self.fixup_state(state)
# Reorder the state.torrents list to add torrents in the correct queue order.
- state.torrents.sort(key=operator.attrgetter('queue'), reverse=self.config['queue_new_to_top'])
+ state.torrents.sort(
+ key=operator.attrgetter('queue'), reverse=self.config['queue_new_to_top']
+ )
resume_data = self.load_resume_data_file()
deferreds = []
@@ -760,7 +853,7 @@ 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')
)
try:
@@ -773,15 +866,24 @@ class TorrentManager(component.Component):
resume_data=resume_data.get(t_state.torrent_id),
)
except AddTorrentError as ex:
- log.warning('Error when adding torrent "%s" to session: %s', t_state.torrent_id, ex)
+ log.warning(
+ 'Error when adding torrent "%s" to session: %s',
+ t_state.torrent_id,
+ ex,
+ )
else:
deferreds.append(d)
deferred_list = DeferredList(deferreds, consumeErrors=False)
def on_complete(result):
- log.info('Finished loading %d torrents in %s', len(state.torrents), str(datetime.datetime.now() - start))
+ log.info(
+ 'Finished loading %d torrents in %s',
+ len(state.torrents),
+ str(datetime.datetime.now() - start),
+ )
component.get('EventManager').emit(SessionStartedEvent())
+
deferred_list.addCallback(on_complete)
def create_state(self):
@@ -850,6 +952,7 @@ class TorrentManager(component.Component):
self.is_saving_state = False
if self.save_state_timer.running:
self.save_state_timer.reset()
+
d.addBoth(on_state_saved)
return d
@@ -910,7 +1013,11 @@ class TorrentManager(component.Component):
"""
if torrent_ids is None:
- torrent_ids = (tid for tid, t in self.torrents.items() if t.handle.need_save_resume_data())
+ torrent_ids = (
+ tid
+ for tid, t in self.torrents.items()
+ if t.handle.need_save_resume_data()
+ )
def on_torrent_resume_save(dummy_result, torrent_id):
"""Recieved torrent resume_data alert so remove from waiting list"""
@@ -994,8 +1101,10 @@ class TorrentManager(component.Component):
if self.save_resume_data_timer.running:
self.save_resume_data_timer.reset()
return arg
+
d.addBoth(on_resume_data_file_saved)
return d
+
return self.save_resume_data_file_lock.run(on_lock_aquired)
def _save_resume_data_file(self):
@@ -1066,7 +1175,9 @@ class TorrentManager(component.Component):
def queue_down(self, torrent_id):
"""Queue torrent down one position"""
- if self.torrents[torrent_id].get_queue_position() == (len(self.queued_torrents) - 1):
+ if self.torrents[torrent_id].get_queue_position() == (
+ len(self.queued_torrents) - 1
+ ):
return False
self.torrents[torrent_id].handle.queue_position_down()
@@ -1074,7 +1185,9 @@ class TorrentManager(component.Component):
def queue_bottom(self, torrent_id):
"""Queue torrent to bottom"""
- if self.torrents[torrent_id].get_queue_position() == (len(self.queued_torrents) - 1):
+ if self.torrents[torrent_id].get_queue_position() == (
+ len(self.queued_torrents) - 1
+ ):
return False
self.torrents[torrent_id].handle.queue_position_bottom()
@@ -1140,21 +1253,28 @@ class TorrentManager(component.Component):
# If total_download is 0, do not move, it's likely the torrent wasn't downloaded, but just added.
# Get fresh data from libtorrent, the cache isn't always up to date
- total_download = torrent.get_status(['total_payload_download'], update=True)['total_payload_download']
+ total_download = torrent.get_status(['total_payload_download'], update=True)[
+ 'total_payload_download'
+ ]
if log.isEnabledFor(logging.DEBUG):
log.debug('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.is_finished,
+ total_download,
+ torrent.options['move_completed'],
torrent.options['move_completed_path'],
)
torrent.update_state()
if not torrent.is_finished and total_download:
# Move completed download to completed folder if needed
- if torrent.options['move_completed'] and \
- torrent.options['download_location'] != torrent.options['move_completed_path']:
+ if (
+ torrent.options['move_completed']
+ and torrent.options['download_location']
+ != torrent.options['move_completed_path']
+ ):
self.waiting_on_finish_moving.append(torrent_id)
torrent.move_storage(torrent.options['move_completed_path'])
else:
@@ -1177,7 +1297,7 @@ class TorrentManager(component.Component):
# worth really to save in resume data, we just read it up in
# self.load_state().
if total_download:
- self.save_resume_data((torrent_id, ))
+ self.save_resume_data((torrent_id,))
def on_alert_torrent_paused(self, alert):
"""Alert handler for libtorrent torrent_paused_alert"""
@@ -1217,7 +1337,10 @@ class TorrentManager(component.Component):
torrent.set_tracker_status('Announce OK')
# Check for peer information from the tracker, if none then send a scrape request.
- if alert.handle.status().num_complete == -1 or alert.handle.status().num_incomplete == -1:
+ if (
+ alert.handle.status().num_complete == -1
+ or alert.handle.status().num_incomplete == -1
+ ):
torrent.scrape_tracker()
def on_alert_tracker_announce(self, alert):
@@ -1249,7 +1372,9 @@ class TorrentManager(component.Component):
error_message = decode_bytes(alert.error_message())
if not error_message:
error_message = decode_bytes(alert.error.message())
- log.debug('Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message)
+ log.debug(
+ 'Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message
+ )
torrent.set_tracker_status('Error: ' + error_message)
def on_alert_storage_moved(self, alert):
@@ -1337,7 +1462,9 @@ class TorrentManager(component.Component):
return
if torrent_id in self.waiting_on_resume_data:
- self.waiting_on_resume_data[torrent_id].errback(Exception(decode_bytes(alert.message())))
+ self.waiting_on_resume_data[torrent_id].errback(
+ Exception(decode_bytes(alert.message()))
+ )
def on_alert_fastresume_rejected(self, alert):
"""Alert handler for libtorrent fastresume_rejected_alert"""
@@ -1355,7 +1482,9 @@ class TorrentManager(component.Component):
else:
error_msg = 'Missing or invalid torrent data!'
else:
- error_msg = 'Problem with resume data: %s' % alert_msg.split(':', 1)[1].strip()
+ error_msg = (
+ 'Problem with resume data: %s' % alert_msg.split(':', 1)[1].strip()
+ )
torrent.force_error_state(error_msg, restart_to_resume=True)
def on_alert_file_renamed(self, alert):
@@ -1381,7 +1510,9 @@ class TorrentManager(component.Component):
break
else:
# This is just a regular file rename so send the signal
- component.get('EventManager').emit(TorrentFileRenamedEvent(torrent_id, alert.index, new_name))
+ component.get('EventManager').emit(
+ TorrentFileRenamedEvent(torrent_id, alert.index, new_name)
+ )
self.save_resume_data((torrent_id,))
def on_alert_metadata_received(self, alert):
@@ -1427,7 +1558,9 @@ class TorrentManager(component.Component):
except RuntimeError:
return
if torrent_id in self.torrents:
- component.get('EventManager').emit(TorrentFileCompletedEvent(torrent_id, alert.index))
+ component.get('EventManager').emit(
+ TorrentFileCompletedEvent(torrent_id, alert.index)
+ )
def on_alert_state_update(self, alert):
"""Alert handler for libtorrent state_update_alert
@@ -1464,7 +1597,11 @@ class TorrentManager(component.Component):
def on_alert_performance(self, alert):
"""Alert handler for libtorrent performance_alert"""
- log.warning('on_alert_performance: %s, %s', decode_bytes(alert.message()), alert.warning_code)
+ log.warning(
+ 'on_alert_performance: %s, %s',
+ decode_bytes(alert.message()),
+ alert.warning_code,
+ )
if alert.warning_code == lt.performance_warning_t.send_buffer_watermark_too_low:
max_send_buffer_watermark = 3 * 1024 * 1024 # 3MiB
settings = self.session.get_settings()
@@ -1473,10 +1610,19 @@ class TorrentManager(component.Component):
# If send buffer is too small, try increasing its size by 512KiB (up to max_send_buffer_watermark)
if send_buffer_watermark < max_send_buffer_watermark:
value = send_buffer_watermark + (500 * 1024)
- log.info('Increasing send_buffer_watermark from %s to %s Bytes', send_buffer_watermark, value)
- component.get('Core').apply_session_setting('send_buffer_watermark', value)
+ log.info(
+ 'Increasing send_buffer_watermark from %s to %s Bytes',
+ send_buffer_watermark,
+ value,
+ )
+ component.get('Core').apply_session_setting(
+ 'send_buffer_watermark', value
+ )
else:
- log.warning('send_buffer_watermark reached maximum value: %s Bytes', max_send_buffer_watermark)
+ log.warning(
+ 'send_buffer_watermark reached maximum value: %s Bytes',
+ max_send_buffer_watermark,
+ )
def separate_keys(self, keys, torrent_ids):
"""Separates the input keys into torrent class keys and plugins keys"""
@@ -1502,7 +1648,9 @@ class TorrentManager(component.Component):
# Could be the clients cache (sessionproxy) isn't up to speed.
del status_dict[torrent_id]
else:
- status_dict[torrent_id] = self.torrents[torrent_id].get_status(torrent_keys, diff, all_keys=not keys)
+ status_dict[torrent_id] = self.torrents[torrent_id].get_status(
+ torrent_keys, diff, all_keys=not keys
+ )
self.status_dict = status_dict
d.callback((status_dict, plugin_keys))
@@ -1527,7 +1675,9 @@ class TorrentManager(component.Component):
now = time.time()
# If last update was recent, use cached data instead of request updates from libtorrent
if (now - self.last_state_update_alert_ts) < 1.5:
- reactor.callLater(0, self.handle_torrents_status_callback, (d, torrent_ids, keys, diff))
+ reactor.callLater(
+ 0, self.handle_torrents_status_callback, (d, torrent_ids, keys, diff)
+ )
else:
# Ask libtorrent for status update
self.torrents_status_requests.insert(0, (d, torrent_ids, keys, diff))
diff --git a/deluge/crypto_utils.py b/deluge/crypto_utils.py
index 7993fb98f..7672efa71 100644
--- a/deluge/crypto_utils.py
+++ b/deluge/crypto_utils.py
@@ -10,7 +10,13 @@
from __future__ import division, print_function, unicode_literals
from OpenSSL.crypto import FILETYPE_PEM
-from twisted.internet.ssl import AcceptableCiphers, Certificate, CertificateOptions, KeyPair, TLSVersion
+from twisted.internet.ssl import (
+ AcceptableCiphers,
+ Certificate,
+ CertificateOptions,
+ KeyPair,
+ TLSVersion,
+)
# A TLS ciphers list.
# Sources for more information on TLS ciphers:
@@ -25,16 +31,17 @@ from twisted.internet.ssl import AcceptableCiphers, Certificate, CertificateOpti
# - prefer cipher suites that offer perfect forward secrecy (ECDHE),
# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
# - disable NULL authentication, MD5 MACs and DSS for security reasons.
-TLS_CIPHERS = ':'.join([
- 'ECDH+AESGCM',
- 'ECDH+CHACHA20',
- 'AES256-GCM-SHA384',
- 'AES128-GCM-SHA256',
- '!DSS'
- '!aNULL',
- '!eNULL',
- '!MD5'
-])
+TLS_CIPHERS = ':'.join(
+ [
+ 'ECDH+AESGCM',
+ 'ECDH+CHACHA20',
+ 'AES256-GCM-SHA384',
+ 'AES128-GCM-SHA256',
+ '!DSS' '!aNULL',
+ '!eNULL',
+ '!MD5',
+ ]
+)
# This value tells OpenSSL to disable all SSL/TLS renegotiation.
SSL_OP_NO_RENEGOTIATION = 0x40000000
diff --git a/deluge/decorators.py b/deluge/decorators.py
index bd0ca02d9..b101712d4 100644
--- a/deluge/decorators.py
+++ b/deluge/decorators.py
@@ -23,11 +23,14 @@ def proxy(proxy_func):
:param proxy_func: the proxy function
:type proxy_func: function
"""
+
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return proxy_func(func, *args, **kwargs)
+
return wrapper
+
return decorator
@@ -57,6 +60,7 @@ def overrides(*args):
# called with the real function as argument
def ret_func(func, **kwargs):
return _overrides(stack, func, explicit_base_classes=args)
+
return ret_func
@@ -75,7 +79,10 @@ def _overrides(stack, method, explicit_base_classes=None):
check_classes = base_classes
if not base_classes:
- raise ValueError('overrides decorator: unable to determine base class of class "%s"' % class_name)
+ raise ValueError(
+ 'overrides decorator: unable to determine base class of class "%s"'
+ % class_name
+ )
def get_class(cls_name):
if '.' not in cls_name:
@@ -91,7 +98,9 @@ def _overrides(stack, method, explicit_base_classes=None):
if explicit_base_classes:
# One or more base classes are explicitly given, check only those classes
- override_classes = re.search(r'\s*@overrides\((.+)\)\s*', stack[1][4][0]).group(1)
+ override_classes = re.search(r'\s*@overrides\((.+)\)\s*', stack[1][4][0]).group(
+ 1
+ )
override_classes = [c.strip() for c in override_classes.split(',')]
check_classes = override_classes
@@ -101,21 +110,36 @@ def _overrides(stack, method, explicit_base_classes=None):
# Verify that the excplicit override class is one of base classes
if explicit_base_classes:
from itertools import product
+
for bc, cc in product(base_classes, check_classes):
if issubclass(classes[bc], classes[cc]):
break
else:
- raise Exception('Excplicit override class "%s" is not a super class of: %s'
- % (explicit_base_classes, class_name))
+ raise Exception(
+ 'Excplicit override class "%s" is not a super class of: %s'
+ % (explicit_base_classes, class_name)
+ )
if not all(hasattr(classes[cls], method.__name__) for cls in check_classes):
for cls in check_classes:
if not hasattr(classes[cls], method.__name__):
- raise Exception('Function override "%s" not found in superclass: %s\n%s'
- % (method.__name__, cls, 'File: %s:%s' % (stack[1][1], stack[1][2])))
+ raise Exception(
+ 'Function override "%s" not found in superclass: %s\n%s'
+ % (
+ method.__name__,
+ cls,
+ 'File: %s:%s' % (stack[1][1], stack[1][2]),
+ )
+ )
if not any(hasattr(classes[cls], method.__name__) for cls in check_classes):
- raise Exception('Function override "%s" not found in any superclass: %s\n%s'
- % (method.__name__, check_classes, 'File: %s:%s' % (stack[1][1], stack[1][2])))
+ raise Exception(
+ 'Function override "%s" not found in any superclass: %s\n%s'
+ % (
+ method.__name__,
+ check_classes,
+ 'File: %s:%s' % (stack[1][1], stack[1][2]),
+ )
+ )
return method
@@ -131,7 +155,8 @@ def deprecated(func):
warnings.simplefilter('always', DeprecationWarning) # Turn off filter
warnings.warn(
'Call to deprecated function {}.'.format(func.__name__),
- category=DeprecationWarning, stacklevel=2,
+ category=DeprecationWarning,
+ stacklevel=2,
)
warnings.simplefilter('default', DeprecationWarning) # Reset filter
return func(*args, **kwargs)
diff --git a/deluge/error.py b/deluge/error.py
index 526168d46..8705fdfe6 100644
--- a/deluge/error.py
+++ b/deluge/error.py
@@ -13,7 +13,6 @@ from __future__ import unicode_literals
class DelugeError(Exception):
-
def __new__(cls, *args, **kwargs):
inst = super(DelugeError, cls).__new__(cls, *args, **kwargs)
inst._args = args
@@ -45,7 +44,6 @@ class InvalidPathError(DelugeError):
class WrappedException(DelugeError):
-
def __init__(self, message, exception_type, traceback):
super(WrappedException, self).__init__(message)
self.type = exception_type
@@ -60,7 +58,6 @@ class _ClientSideRecreateError(DelugeError):
class IncompatibleClient(_ClientSideRecreateError):
-
def __init__(self, daemon_version):
self.daemon_version = daemon_version
msg = (
@@ -71,11 +68,8 @@ class IncompatibleClient(_ClientSideRecreateError):
class NotAuthorizedError(_ClientSideRecreateError):
-
def __init__(self, current_level, required_level):
- msg = (
- 'Auth level too low: %(current_level)s < %(required_level)s'
- ) % {
+ msg = ('Auth level too low: %(current_level)s < %(required_level)s') % {
'current_level': current_level,
'required_level': required_level,
}
@@ -85,7 +79,6 @@ class NotAuthorizedError(_ClientSideRecreateError):
class _UsernameBasedPasstroughError(_ClientSideRecreateError):
-
def __init__(self, message, username):
super(_UsernameBasedPasstroughError, self).__init__(message)
self.username = username
diff --git a/deluge/event.py b/deluge/event.py
index b6a48508b..c5d5ff910 100644
--- a/deluge/event.py
+++ b/deluge/event.py
@@ -25,6 +25,7 @@ class DelugeEventMetaClass(type):
"""
This metaclass simply keeps a list of all events classes created.
"""
+
def __init__(cls, name, bases, dct): # pylint: disable=bad-mcs-method-argument
super(DelugeEventMetaClass, cls).__init__(name, bases, dct)
if name != 'DelugeEvent':
@@ -58,6 +59,7 @@ class TorrentAddedEvent(DelugeEvent):
"""
Emitted when a new torrent is successfully added to the session.
"""
+
def __init__(self, torrent_id, from_state):
"""
:param torrent_id: the torrent_id of the torrent that was added
@@ -72,6 +74,7 @@ class TorrentRemovedEvent(DelugeEvent):
"""
Emitted when a torrent has been removed from the session.
"""
+
def __init__(self, torrent_id):
"""
:param torrent_id: the torrent_id
@@ -84,6 +87,7 @@ class PreTorrentRemovedEvent(DelugeEvent):
"""
Emitted when a torrent is about to be removed from the session.
"""
+
def __init__(self, torrent_id):
"""
:param torrent_id: the torrent_id
@@ -96,6 +100,7 @@ class TorrentStateChangedEvent(DelugeEvent):
"""
Emitted when a torrent changes state.
"""
+
def __init__(self, torrent_id, state):
"""
:param torrent_id: the torrent_id
@@ -110,6 +115,7 @@ class TorrentTrackerStatusEvent(DelugeEvent):
"""
Emitted when a torrents tracker status changes.
"""
+
def __init__(self, torrent_id, status):
"""
Args:
@@ -123,6 +129,7 @@ class TorrentQueueChangedEvent(DelugeEvent):
"""
Emitted when the queue order has changed.
"""
+
pass
@@ -130,6 +137,7 @@ class TorrentFolderRenamedEvent(DelugeEvent):
"""
Emitted when a folder within a torrent has been renamed.
"""
+
def __init__(self, torrent_id, old, new):
"""
:param torrent_id: the torrent_id
@@ -146,6 +154,7 @@ class TorrentFileRenamedEvent(DelugeEvent):
"""
Emitted when a file within a torrent has been renamed.
"""
+
def __init__(self, torrent_id, index, name):
"""
:param torrent_id: the torrent_id
@@ -162,6 +171,7 @@ class TorrentFinishedEvent(DelugeEvent):
"""
Emitted when a torrent finishes downloading.
"""
+
def __init__(self, torrent_id):
"""
:param torrent_id: the torrent_id
@@ -174,6 +184,7 @@ class TorrentResumedEvent(DelugeEvent):
"""
Emitted when a torrent resumes from a paused state.
"""
+
def __init__(self, torrent_id):
"""
:param torrent_id: the torrent_id
@@ -186,6 +197,7 @@ class TorrentFileCompletedEvent(DelugeEvent):
"""
Emitted when a file completes.
"""
+
def __init__(self, torrent_id, index):
"""
:param torrent_id: the torrent_id
@@ -200,6 +212,7 @@ class TorrentStorageMovedEvent(DelugeEvent):
"""
Emitted when the storage location for a torrent has been moved.
"""
+
def __init__(self, torrent_id, path):
"""
:param torrent_id: the torrent_id
@@ -214,6 +227,7 @@ class CreateTorrentProgressEvent(DelugeEvent):
"""
Emitted when creating a torrent file remotely.
"""
+
def __init__(self, piece_count, num_pieces):
self._args = [piece_count, num_pieces]
@@ -222,6 +236,7 @@ class NewVersionAvailableEvent(DelugeEvent):
"""
Emitted when a more recent version of Deluge is available.
"""
+
def __init__(self, new_release):
"""
:param new_release: the new version that is available
@@ -235,6 +250,7 @@ class SessionStartedEvent(DelugeEvent):
Emitted when a session has started. This typically only happens once when
the daemon is initially started.
"""
+
pass
@@ -242,6 +258,7 @@ class SessionPausedEvent(DelugeEvent):
"""
Emitted when the session has been paused.
"""
+
pass
@@ -249,6 +266,7 @@ class SessionResumedEvent(DelugeEvent):
"""
Emitted when the session has been resumed.
"""
+
pass
@@ -256,6 +274,7 @@ class ConfigValueChangedEvent(DelugeEvent):
"""
Emitted when a config value changes in the Core.
"""
+
def __init__(self, key, value):
"""
:param key: the key that changed
@@ -269,6 +288,7 @@ class PluginEnabledEvent(DelugeEvent):
"""
Emitted when a plugin is enabled in the Core.
"""
+
def __init__(self, plugin_name):
self._args = [plugin_name]
@@ -277,6 +297,7 @@ class PluginDisabledEvent(DelugeEvent):
"""
Emitted when a plugin is disabled in the Core.
"""
+
def __init__(self, plugin_name):
self._args = [plugin_name]
@@ -285,6 +306,7 @@ class ClientDisconnectedEvent(DelugeEvent):
"""
Emitted when a client disconnects.
"""
+
def __init__(self, session_id):
self._args = [session_id]
@@ -293,6 +315,7 @@ class ExternalIPEvent(DelugeEvent):
"""
Emitted when the external ip address is received from libtorrent.
"""
+
def __init__(self, external_ip):
"""
Args:
diff --git a/deluge/httpdownloader.py b/deluge/httpdownloader.py
index ad0d2f80a..b4acd0784 100644
--- a/deluge/httpdownloader.py
+++ b/deluge/httpdownloader.py
@@ -31,13 +31,14 @@ log = logging.getLogger(__name__)
class CompressionDecoder(client.GzipDecoder):
"""A compression decoder for gzip, x-gzip and deflate."""
+
def deliverBody(self, protocol): # NOQA: N802
- self.original.deliverBody(
- CompressionDecoderProtocol(protocol, self.original))
+ self.original.deliverBody(CompressionDecoderProtocol(protocol, self.original))
class CompressionDecoderProtocol(client._GzipProtocol):
"""A compression decoder protocol for CompressionDecoder."""
+
def __init__(self, protocol, response):
super(CompressionDecoderProtocol, self).__init__(protocol, response)
self._zlibDecompress = zlib.decompressobj(32 + zlib.MAX_WBITS)
@@ -45,6 +46,7 @@ class CompressionDecoderProtocol(client._GzipProtocol):
class BodyHandler(HTTPClientParser, object):
"""An HTTP parser that saves the response to a file."""
+
def __init__(self, request, finished, length, agent, encoding=None):
"""BodyHandler init.
@@ -66,8 +68,7 @@ class BodyHandler(HTTPClientParser, object):
self.current_length += len(data)
self.data += data
if self.agent.part_callback:
- self.agent.part_callback(
- data, self.current_length, self.total_length)
+ self.agent.part_callback(data, self.current_length, self.total_length)
def connectionLost(self, reason): # NOQA: N802
if self.encoding:
@@ -82,6 +83,7 @@ class BodyHandler(HTTPClientParser, object):
@implementer(IAgent)
class HTTPDownloaderAgent(object):
"""A File Downloader Agent."""
+
def __init__(
self,
agent,
@@ -125,21 +127,19 @@ class HTTPDownloaderAgent(object):
finished.errback(Failure(error))
else:
headers = response.headers
- body_length = int(
- headers.getRawHeaders(b'content-length', default=[0])[0])
-
- if (
- headers.hasHeader(b'content-disposition')
- and not self.force_filename
- ):
- content_disp = headers.getRawHeaders(
- b'content-disposition')[0].decode('utf-8')
+ body_length = int(headers.getRawHeaders(b'content-length', default=[0])[0])
+
+ if headers.hasHeader(b'content-disposition') and not self.force_filename:
+ content_disp = headers.getRawHeaders(b'content-disposition')[0].decode(
+ 'utf-8'
+ )
content_disp_params = cgi.parse_header(content_disp)[1]
if 'filename' in content_disp_params:
new_file_name = content_disp_params['filename']
new_file_name = sanitise_filename(new_file_name)
new_file_name = os.path.join(
- os.path.split(self.filename)[0], new_file_name)
+ os.path.split(self.filename)[0], new_file_name
+ )
count = 1
fileroot = os.path.splitext(new_file_name)[0]
@@ -155,13 +155,8 @@ class HTTPDownloaderAgent(object):
params = cgi.parse_header(cont_type)[1]
encoding = params.get('charset', None)
response.deliverBody(
- BodyHandler(
- response.request,
- finished,
- body_length,
- self,
- encoding,
- ))
+ BodyHandler(response.request, finished, body_length, self, encoding)
+ )
return finished
@@ -186,10 +181,7 @@ class HTTPDownloaderAgent(object):
headers.addRawHeader('User-Agent', user_agent)
d = self.agent.request(
- method=method,
- uri=uri,
- headers=headers,
- bodyProducer=body_producer,
+ method=method, uri=uri, headers=headers, bodyProducer=body_producer
)
d.addCallback(self.request_callback)
return d
@@ -212,8 +204,7 @@ def sanitise_filename(filename):
if os.path.basename(filename) != filename:
# Dodgy server, log it
log.warning(
- 'Potentially malicious server: trying to write to file: %s',
- filename,
+ 'Potentially malicious server: trying to write to file: %s', filename
)
# Only use the basename
filename = os.path.basename(filename)
@@ -222,15 +213,15 @@ def sanitise_filename(filename):
if filename.startswith('.') or ';' in filename or '|' in filename:
# Dodgy server, log it
log.warning(
- 'Potentially malicious server: trying to write to file: %s',
- filename,
+ 'Potentially malicious server: trying to write to file: %s', filename
)
return filename
def _download_file(
- url, filename,
+ url,
+ filename,
callback=None,
headers=None,
force_filename=False,
@@ -269,12 +260,7 @@ def _download_file(
agent = client.RedirectAgent(agent)
agent = HTTPDownloaderAgent(
- agent,
- filename,
- callback,
- force_filename,
- allow_compression,
- handle_redirects,
+ agent, filename, callback, force_filename, allow_compression, handle_redirects
)
# The Headers init expects dict values to be a list.
@@ -317,6 +303,7 @@ def download_file(
t.w.e.PageRedirect: If handle_redirects is False.
t.w.e.Error: For all other HTTP response errors.
"""
+
def on_download_success(result):
log.debug('Download success!')
return result
@@ -324,14 +311,19 @@ def download_file(
def on_download_fail(failure):
log.warning(
'Error occurred downloading file from "%s": %s',
- url, failure.getErrorMessage(),
+ url,
+ failure.getErrorMessage(),
)
result = failure
return result
d = _download_file(
- url, filename, callback=callback, headers=headers,
- force_filename=force_filename, allow_compression=allow_compression,
+ url,
+ filename,
+ callback=callback,
+ headers=headers,
+ force_filename=force_filename,
+ allow_compression=allow_compression,
handle_redirects=handle_redirects,
)
d.addCallbacks(on_download_success, on_download_fail)
diff --git a/deluge/log.py b/deluge/log.py
index ba0af4c8b..e2e718e40 100644
--- a/deluge/log.py
+++ b/deluge/log.py
@@ -29,7 +29,9 @@ LoggingLoggerClass = logging.getLoggerClass()
if 'dev' in common.get_version():
DEFAULT_LOGGING_FORMAT = '%%(asctime)s.%%(msecs)03.0f [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s'
else:
- DEFAULT_LOGGING_FORMAT = '%%(asctime)s [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s'
+ DEFAULT_LOGGING_FORMAT = (
+ '%%(asctime)s [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s'
+ )
MAX_LOGGER_NAME_LENGTH = 10
@@ -43,10 +45,12 @@ class Logging(LoggingLoggerClass):
if len(logger_name) > MAX_LOGGER_NAME_LENGTH:
MAX_LOGGER_NAME_LENGTH = len(logger_name)
for handler in logging.getLogger().handlers:
- handler.setFormatter(logging.Formatter(
- DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH,
- datefmt='%H:%M:%S',
- ))
+ handler.setFormatter(
+ logging.Formatter(
+ DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH,
+ datefmt='%H:%M:%S',
+ )
+ )
@defer.inlineCallbacks
def garbage(self, msg, *args, **kwargs):
@@ -112,8 +116,12 @@ levels = {
def setup_logger(
- level='error', filename=None, filemode='w', logrotate=None,
- output_stream=sys.stdout, twisted_observer=True,
+ 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
@@ -140,13 +148,14 @@ def setup_logger(
if filename and logrotate:
handler = logging.handlers.RotatingFileHandler(
- filename, maxBytes=logrotate,
- backupCount=5, encoding='utf-8',
+ filename, maxBytes=logrotate, backupCount=5, encoding='utf-8'
)
elif filename and filemode == 'w':
handler_cls = logging.FileHandler
if not common.windows_check():
- handler_cls = getattr(logging.handlers, 'WatchedFileHandler', logging.FileHandler)
+ handler_cls = getattr(
+ logging.handlers, 'WatchedFileHandler', logging.FileHandler
+ )
handler = handler_cls(filename, mode=filemode, encoding='utf-8')
else:
handler = logging.StreamHandler(stream=output_stream)
@@ -154,8 +163,7 @@ def setup_logger(
handler.setLevel(level)
formatter = logging.Formatter(
- DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH,
- datefmt='%H:%M:%S',
+ DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH, datefmt='%H:%M:%S'
)
handler.setFormatter(formatter)
@@ -190,7 +198,9 @@ class TwistedLoggingObserver(PythonLoggingObserver):
log = logging.getLogger(__name__)
if 'log_failure' in event_dict:
fmt = '%(log_namespace)s \n%(log_failure)s'
- getattr(LoggingLoggerClass, event_dict['log_level'].name)(log, fmt % (event_dict))
+ getattr(LoggingLoggerClass, event_dict['log_level'].name)(
+ log, fmt % (event_dict)
+ )
else:
PythonLoggingObserver.emit(self, event_dict)
@@ -214,13 +224,13 @@ def tweak_logging_levels():
the command line.
"""
from deluge import configmanager
+
logging_config_file = os.path.join(configmanager.get_config_dir(), 'logging.conf')
if not os.path.isfile(logging_config_file):
return
log = logging.getLogger(__name__)
log.warning(
- 'logging.conf found! tweaking logging levels from %s',
- logging_config_file,
+ 'logging.conf found! tweaking logging levels from %s', logging_config_file
)
with open(logging_config_file, 'r') as _file:
for line in _file:
@@ -249,15 +259,18 @@ def set_logger_level(level, logger_name=None):
def get_plugin_logger(logger_name):
import warnings
+
stack = inspect.stack()
- stack.pop(0) # The logging call from this module
+ stack.pop(0) # The logging call from this module
module_stack = stack.pop(0) # The module that called the log function
caller_module = inspect.getmodule(module_stack[0])
# In some weird cases caller_module might be None, try to continue
caller_module_name = getattr(caller_module, '__name__', '')
warnings.warn_explicit(
- DEPRECATION_WARNING, DeprecationWarning,
- module_stack[1], module_stack[2],
+ DEPRECATION_WARNING,
+ DeprecationWarning,
+ module_stack[1],
+ module_stack[2],
caller_module_name,
)
@@ -292,16 +305,19 @@ Triggering code:"""
class _BackwardsCompatibleLOG(object):
def __getattribute__(self, name):
import warnings
+
logger_name = 'deluge'
stack = inspect.stack()
- stack.pop(0) # The logging call from this module
+ stack.pop(0) # The logging call from this module
module_stack = stack.pop(0) # The module that called the log function
caller_module = inspect.getmodule(module_stack[0])
# In some weird cases caller_module might be None, try to continue
caller_module_name = getattr(caller_module, '__name__', '')
warnings.warn_explicit(
- DEPRECATION_WARNING, DeprecationWarning,
- module_stack[1], module_stack[2],
+ DEPRECATION_WARNING,
+ DeprecationWarning,
+ module_stack[1],
+ module_stack[2],
caller_module_name,
)
if caller_module:
@@ -320,7 +336,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)
diff --git a/deluge/maketorrent.py b/deluge/maketorrent.py
index 7ea64746c..528638e43 100644
--- a/deluge/maketorrent.py
+++ b/deluge/maketorrent.py
@@ -18,6 +18,7 @@ from deluge.common import get_path_size, utf8_encode_structure
class InvalidPath(Exception):
"""Raised when an invalid path is supplied."""
+
pass
@@ -27,6 +28,7 @@ class InvalidPieceSize(Exception):
Note:
Piece sizes must be multiples of 16KiB.
"""
+
pass
@@ -42,6 +44,7 @@ class TorrentMetadata(object):
>>> t.save('/tmp/test.torrent')
"""
+
def __init__(self):
self.__data_path = None
self.__piece_size = 0
@@ -66,9 +69,7 @@ class TorrentMetadata(object):
if not self.data_path:
raise InvalidPath('Need to set a data_path!')
- torrent = {
- 'info': {},
- }
+ torrent = {'info': {}}
if self.comment:
torrent['comment'] = self.comment
@@ -121,8 +122,10 @@ class TorrentMetadata(object):
# Collect a list of file paths and add padding files if necessary
for (dirpath, dirnames, filenames) in os.walk(self.data_path):
for index, filename in enumerate(filenames):
- size = get_path_size(os.path.join(self.data_path, dirpath, filename))
- p = dirpath[len(self.data_path):]
+ size = get_path_size(
+ os.path.join(self.data_path, dirpath, filename)
+ )
+ p = dirpath[len(self.data_path) :]
p = p.lstrip('/')
p = p.split('/')
if p[0]:
@@ -156,7 +159,9 @@ class TorrentMetadata(object):
buf = b''
fs[-1][b'attr'] = b'p'
else:
- with open(os.path.join(self.data_path.encode('utf8'), *path), 'rb') as _file:
+ with open(
+ os.path.join(self.data_path.encode('utf8'), *path), 'rb'
+ ) as _file:
r = _file.read(piece_size - len(buf))
while r:
buf += r
diff --git a/deluge/metafile.py b/deluge/metafile.py
index 29c020e9f..8c28c7e91 100644
--- a/deluge/metafile.py
+++ b/deluge/metafile.py
@@ -50,14 +50,25 @@ 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,
+ 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:
@@ -140,6 +151,7 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private
totalsize += os.path.getsize(f)
if totalsize >= piece_length:
import math
+
num_pieces = math.ceil(totalsize / piece_length)
else:
num_pieces = 1
@@ -149,10 +161,9 @@ 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_:
@@ -206,14 +217,16 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private
if content_type is not None:
return {
'pieces': b''.join(pieces),
- 'piece length': piece_length, 'length': size,
+ 'piece length': piece_length,
+ 'length': size,
'name': name,
'content_type': content_type,
'private': private,
}
return {
'pieces': b''.join(pieces),
- 'piece length': piece_length, 'length': size,
+ 'piece length': piece_length,
+ 'length': size,
'name': name,
'private': private,
}
diff --git a/deluge/path_chooser_common.py b/deluge/path_chooser_common.py
index d6cd27c40..b84d78ef9 100644
--- a/deluge/path_chooser_common.py
+++ b/deluge/path_chooser_common.py
@@ -17,9 +17,12 @@ def is_hidden(filepath):
def has_hidden_attribute(filepath):
import win32api
import win32con
+
try:
attribute = win32api.GetFileAttributes(filepath)
- return attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM)
+ return attribute & (
+ win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM
+ )
except (AttributeError, AssertionError):
return False
diff --git a/deluge/pluginmanagerbase.py b/deluge/pluginmanagerbase.py
index 624b06b05..0a84c1b1c 100644
--- a/deluge/pluginmanagerbase.py
+++ b/deluge/pluginmanagerbase.py
@@ -56,7 +56,9 @@ class PluginManagerBase(object):
self.config = deluge.configmanager.ConfigManager(config_file)
# Create the plugins folder if it doesn't exist
- if not os.path.exists(os.path.join(deluge.configmanager.get_config_dir(), 'plugins')):
+ if not os.path.exists(
+ os.path.join(deluge.configmanager.get_config_dir(), 'plugins')
+ ):
os.mkdir(os.path.join(deluge.configmanager.get_config_dir(), 'plugins'))
# This is the entry we want to load..
@@ -149,7 +151,9 @@ class PluginManagerBase(object):
log.error(ex)
return defer.succeed(False)
except Exception as ex:
- log.error('Unable to instantiate plugin %r from %r!', name, egg.location)
+ log.error(
+ 'Unable to instantiate plugin %r from %r!', name, egg.location
+ )
log.exception(ex)
continue
try:
@@ -161,35 +165,47 @@ class PluginManagerBase(object):
if not instance.__module__.startswith('deluge.plugins.'):
import warnings
+
warnings.warn_explicit(
DEPRECATION_WARNING % name,
DeprecationWarning,
- instance.__module__, 0,
+ instance.__module__,
+ 0,
)
if self._component_state == 'Started':
+
def on_enabled(result, instance):
return component.start([instance.plugin._component_name])
+
return_d.addCallback(on_enabled, instance)
def on_started(result, instance):
plugin_name_space = plugin_name.replace('-', ' ')
self.plugins[plugin_name_space] = instance
if plugin_name_space not in self.config['enabled_plugins']:
- log.debug('Adding %s to enabled_plugins list in config', plugin_name_space)
+ log.debug(
+ 'Adding %s to enabled_plugins list in config', plugin_name_space
+ )
self.config['enabled_plugins'].append(plugin_name_space)
log.info('Plugin %s enabled...', plugin_name_space)
return True
def on_started_error(result, instance):
log.error(
- 'Failed to start plugin: %s\n%s', plugin_name,
+ '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
- return_d.addCallbacks(on_started, on_started_error, callbackArgs=[instance], errbackArgs=[instance])
+ return_d.addCallbacks(
+ on_started,
+ on_started_error,
+ callbackArgs=[instance],
+ errbackArgs=[instance],
+ )
return return_d
return defer.succeed(False)
@@ -219,7 +235,9 @@ class PluginManagerBase(object):
def on_disabled(result):
ret = True
if isinstance(result, Failure):
- log.debug('Error when disabling plugin %s: %s', name, result.getTraceback())
+ log.debug(
+ 'Error when disabling plugin %s: %s', name, result.getTraceback()
+ )
ret = False
try:
component.deregister(self.plugins[name].plugin)
@@ -250,7 +268,9 @@ class PluginManagerBase(object):
for line in self.pkg_env[name][0].get_metadata('PKG-INFO').splitlines():
if not line:
continue
- if line[0] in ' \t' and (len(line.split(':', 1)) == 1 or line.split(':', 1)[0] not in info):
+ if line[0] in ' \t' and (
+ len(line.split(':', 1)) == 1 or line.split(':', 1)[0] not in info
+ ):
# This is a continuation
cont_lines.append(line.strip())
else:
diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/__init__.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/__init__.py
index 74d8be491..b93d89a45 100644
--- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/__init__.py
+++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/__init__.py
@@ -20,6 +20,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -27,6 +28,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -34,5 +36,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py
index d23f94aae..658a163d5 100644
--- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py
+++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/core.py
@@ -35,10 +35,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
-DEFAULT_PREFS = {
- 'watchdirs': {},
- 'next_id': 1,
-}
+DEFAULT_PREFS = {'watchdirs': {}, 'next_id': 1}
OPTIONS_AVAILABLE = { # option: builtin
@@ -72,6 +69,7 @@ MAX_NUM_ATTEMPTS = 10
class AutoaddOptionsChangedEvent(DelugeEvent):
"""Emitted when the options for the plugin are changed."""
+
def __init__(self):
pass
@@ -92,7 +90,7 @@ class Core(CorePluginBase):
self.rpcserver = component.get('RPCServer')
component.get('EventManager').register_event_handler(
- 'PreTorrentRemovedEvent', self.__on_pre_torrent_removed,
+ 'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
)
# Dict of Filename:Attempts
@@ -110,7 +108,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,14 +122,10 @@ class Core(CorePluginBase):
"""Update the options for a watch folder."""
watchdir_id = str(watchdir_id)
options = self._make_unicode(options)
- check_input(
- watchdir_id in self.watchdirs, _('Watch folder does not exist.'),
- )
+ check_input(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.'),
- )
+ check_input(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:
raise Exception('Path is already being watched.')
@@ -211,10 +205,7 @@ 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
@@ -231,7 +222,10 @@ class Core(CorePluginBase):
# without them is valid, and applies all its settings.
for option, value in watchdir.items():
if OPTIONS_AVAILABLE.get(option):
- if watchdir.get(option + '_toggle', True) or option in ['owner', 'seed_mode']:
+ if watchdir.get(option + '_toggle', True) or option in [
+ 'owner',
+ 'seed_mode',
+ ]:
options[option] = value
# Check for .magnet files containing multiple magnet links and
@@ -240,19 +234,27 @@ class Core(CorePluginBase):
try:
filepath = os.path.join(watchdir['abspath'], filename)
except UnicodeDecodeError as ex:
- log.error('Unable to auto add torrent due to improper filename encoding: %s', ex)
+ log.error(
+ 'Unable to auto add torrent due to improper filename encoding: %s',
+ ex,
+ )
continue
if os.path.isdir(filepath):
# Skip directories
continue
- elif os.path.splitext(filename)[1] == '.magnet' and self.split_magnets(filepath):
+ elif os.path.splitext(filename)[1] == '.magnet' and self.split_magnets(
+ filepath
+ ):
os.remove(filepath)
for filename in os.listdir(watchdir['abspath']):
try:
filepath = os.path.join(watchdir['abspath'], filename)
except UnicodeDecodeError as ex:
- log.error('Unable to auto add torrent due to improper filename encoding: %s', ex)
+ log.error(
+ 'Unable to auto add torrent due to improper filename encoding: %s',
+ ex,
+ )
continue
if os.path.isdir(filepath):
@@ -276,7 +278,8 @@ class Core(CorePluginBase):
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,
+ 'torrent file with the path %s',
+ filepath,
)
os.rename(filepath, filepath + '.invalid')
del self.invalid_torrents[filename]
@@ -296,7 +299,10 @@ class Core(CorePluginBase):
except Exception as ex:
log.error('Unable to set label: %s', ex)
- if watchdir.get('queue_to_top_toggle', True) and 'queue_to_top' in watchdir:
+ if (
+ watchdir.get('queue_to_top_toggle', True)
+ and 'queue_to_top' in watchdir
+ ):
if watchdir['queue_to_top']:
component.get('TorrentManager').queue_top(torrent_id)
else:
@@ -312,7 +318,8 @@ class Core(CorePluginBase):
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,
+ os.path.basename(filepath),
+ copy_torrent_path,
)
shutil.move(filepath, copy_torrent_file)
else:
@@ -331,10 +338,12 @@ class Core(CorePluginBase):
try:
# The torrent looks good, so lets add it to the session.
if magnet:
- d = component.get('Core').add_torrent_magnet(filedump.strip(), options)
+ d = component.get('Core').add_torrent_magnet(
+ filedump.strip(), options
+ )
else:
d = component.get('Core').add_torrent_file_async(
- filename, b64encode(filedump), options,
+ filename, b64encode(filedump), options
)
d.addCallback(on_torrent_added, filename, filepath)
d.addErrback(fail_torrent_add, filepath, magnet)
@@ -346,7 +355,8 @@ class Core(CorePluginBase):
self.disable_watchdir(watchdir_id)
log.error(
'Disabling "%s", error during update: %s',
- self.watchdirs[watchdir_id]['path'], failure,
+ self.watchdirs[watchdir_id]['path'],
+ failure,
)
@export
@@ -356,7 +366,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']:
@@ -398,8 +408,8 @@ class Core(CorePluginBase):
session_auth_level = self.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,
+ 'Current logged in user %s is an ADMIN, send all ' 'watchdirs',
+ session_user,
)
return self.watchdirs
@@ -410,7 +420,9 @@ class Core(CorePluginBase):
log.debug(
'Current logged in user %s is not an ADMIN, send only '
- 'their watchdirs: %s', session_user, list(watchdirs),
+ 'their watchdirs: %s',
+ session_user,
+ list(watchdirs),
)
return watchdirs
@@ -451,7 +463,9 @@ class Core(CorePluginBase):
def remove(self, watchdir_id):
"""Remove a watch folder."""
watchdir_id = str(watchdir_id)
- check_input(watchdir_id in self.watchdirs, 'Unknown Watchdir: %s' % self.watchdirs)
+ check_input(
+ watchdir_id in self.watchdirs, 'Unknown Watchdir: %s' % self.watchdirs
+ )
if self.watchdirs[watchdir_id]['enabled']:
self.disable_watchdir(watchdir_id)
del self.watchdirs[watchdir_id]
@@ -488,13 +502,16 @@ class Core(CorePluginBase):
os.remove(torrent_fname_path)
log.info(
'Removed torrent file "%s" from "%s"',
- torrent_fname, copy_torrent_path,
+ 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,
+ torrent_fname,
+ copy_torrent_path,
+ ex,
)
@export
diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py
index 083a1bcb2..99a70c04f 100644
--- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py
+++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py
@@ -38,8 +38,12 @@ 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',
+ 'stop_at_ratio',
+ 'remove_at_ratio',
+ 'move_completed',
+ 'add_paused',
+ 'auto_managed',
+ 'queue_to_top',
]
def __init__(self):
@@ -52,13 +56,15 @@ class OptionsDialog(object):
options = {}
self.builder = gtk.Builder()
self.builder.add_from_file(get_resource('autoadd_options.ui'))
- self.builder.connect_signals({
- 'on_opts_add': self.on_add,
- 'on_opts_apply': self.on_apply,
- 'on_opts_cancel': self.on_cancel,
- 'on_options_dialog_close': self.on_cancel,
- 'on_toggle_toggled': self.on_toggle_toggled,
- })
+ self.builder.connect_signals(
+ {
+ 'on_opts_add': self.on_add,
+ 'on_opts_apply': self.on_apply,
+ 'on_opts_cancel': self.on_cancel,
+ 'on_options_dialog_close': self.on_cancel,
+ 'on_toggle_toggled': self.on_toggle_toggled,
+ }
+ )
self.dialog = self.builder.get_object('options_dialog')
self.dialog.set_transient_for(component.get('Preferences').pref_dialog)
@@ -79,23 +85,21 @@ 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),
- )
- self.builder.get_object('seed_mode').set_active(
- options.get('seed_mode', False),
+ options.get('delete_copy_torrent_toggle', False)
)
+ self.builder.get_object('seed_mode').set_active(options.get('seed_mode', False))
self.accounts.clear()
self.labels.clear()
combobox = self.builder.get_object('OwnerCombobox')
@@ -108,14 +112,20 @@ class OptionsDialog(object):
label_widget.child.set_text(options.get('label', ''))
label_widget.set_model(self.labels)
label_widget.set_entry_text_column(0)
- self.builder.get_object('label_toggle').set_active(options.get('label_toggle', False))
+ self.builder.get_object('label_toggle').set_active(
+ options.get('label_toggle', False)
+ )
for spin_id in self.spin_ids + self.spin_int_ids:
self.builder.get_object(spin_id).set_value(options.get(spin_id, 0))
- self.builder.get_object(spin_id + '_toggle').set_active(options.get(spin_id + '_toggle', False))
+ self.builder.get_object(spin_id + '_toggle').set_active(
+ options.get(spin_id + '_toggle', False)
+ )
for chk_id in self.chk_ids:
self.builder.get_object(chk_id).set_active(bool(options.get(chk_id, True)))
- self.builder.get_object(chk_id + '_toggle').set_active(options.get(chk_id + '_toggle', False))
+ self.builder.get_object(chk_id + '_toggle').set_active(
+ options.get(chk_id + '_toggle', False)
+ )
if not options.get('add_paused', True):
self.builder.get_object('isnt_add_paused').set_active(True)
if not options.get('queue_to_top', True):
@@ -123,18 +133,20 @@ class OptionsDialog(object):
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',
+ '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()
@@ -143,36 +155,44 @@ 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']),
+ self.builder.get_object(
+ 'move_completed_path_chooser'
+ ).set_current_folder(
+ 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']):
+ if options.get(
+ 'delete_copy_torrent_toggle', config['del_copy_torrent_file']
+ ):
self.builder.get_object('delete_copy_torrent_toggle').set_active(True)
if not options:
@@ -183,9 +203,7 @@ class OptionsDialog(object):
selected_iter = None
for account in accounts:
acc_iter = self.accounts.append()
- self.accounts.set_value(
- acc_iter, 0, account['username'],
- )
+ self.accounts.set_value(acc_iter, 0, account['username'])
if account['username'] == owner:
selected_iter = acc_iter
self.builder.get_object('OwnerCombobox').set_active_iter(selected_iter)
@@ -219,7 +237,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()
@@ -229,11 +247,19 @@ class OptionsDialog(object):
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',
+ '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'))
@@ -249,9 +275,13 @@ class OptionsDialog(object):
elif toggle == 'copy_torrent':
self.builder.get_object('copy_torrent_entry').set_sensitive(isactive)
self.builder.get_object('copy_torrent_chooser').set_sensitive(isactive)
- self.builder.get_object('delete_copy_torrent_toggle').set_sensitive(isactive)
+ self.builder.get_object('delete_copy_torrent_toggle').set_sensitive(
+ isactive
+ )
elif toggle == 'move_completed':
- self.builder.get_object('move_completed_path_chooser').set_sensitive(isactive)
+ self.builder.get_object('move_completed_path_chooser').set_sensitive(
+ isactive
+ )
self.builder.get_object('move_completed_path_entry').set_sensitive(isactive)
self.builder.get_object('move_completed').set_active(isactive)
elif toggle == 'label':
@@ -283,9 +313,9 @@ class OptionsDialog(object):
def on_apply(self, event=None):
try:
options = self.generate_opts()
- client.autoadd.set_options(
- str(self.watchdir_id), options,
- ).addCallbacks(self.on_added, self.on_error_show)
+ client.autoadd.set_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()
@@ -314,54 +344,72 @@ 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',
+ 'download_location_chooser'
).get_filename()
options['move_completed_path'] = self.builder.get_object(
- 'move_completed_path_chooser',
+ 'move_completed_path_chooser'
).get_filename()
options['copy_torrent'] = self.builder.get_object(
- 'copy_torrent_chooser',
+ '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',
+ 'download_location_entry'
).get_text()
options['move_completed_path'] = self.builder.get_object(
- 'move_completed_path_entry',
+ 'move_completed_path_entry'
).get_text()
options['copy_torrent'] = self.builder.get_object(
- 'copy_torrent_entry',
+ '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['append_extension'] = self.builder.get_object(
+ 'append_extension'
+ ).get_text()
options['owner'] = self.accounts[
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',
+ '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:
options[spin_id] = self.builder.get_object(spin_id).get_value()
- options[spin_id + '_toggle'] = self.builder.get_object(spin_id + '_toggle').get_active()
+ options[spin_id + '_toggle'] = self.builder.get_object(
+ spin_id + '_toggle'
+ ).get_active()
for spin_int_id in self.spin_int_ids:
- options[spin_int_id] = self.builder.get_object(spin_int_id).get_value_as_int()
- options[spin_int_id + '_toggle'] = self.builder.get_object(spin_int_id + '_toggle').get_active()
+ options[spin_int_id] = self.builder.get_object(
+ spin_int_id
+ ).get_value_as_int()
+ options[spin_int_id + '_toggle'] = self.builder.get_object(
+ spin_int_id + '_toggle'
+ ).get_active()
for chk_id in self.chk_ids:
options[chk_id] = self.builder.get_object(chk_id).get_active()
- 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!',
- ))
+ 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!'
+ )
+ )
return options
@@ -374,13 +422,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 = {}
@@ -403,31 +451,35 @@ 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):
store = gtk.ListStore(str, bool, str, str)
for watchdir_id, watchdir in self.watchdirs.items():
- store.append([
- watchdir_id, watchdir['enabled'],
- watchdir.get('owner', 'localclient'), watchdir['path'],
- ])
+ store.append(
+ [
+ watchdir_id,
+ watchdir['enabled'],
+ 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)
@@ -505,10 +557,14 @@ class GtkUI(GtkPluginBase):
self.watchdirs = watchdirs or {}
self.store.clear()
for watchdir_id, watchdir in self.watchdirs.items():
- self.store.append([
- watchdir_id, watchdir['enabled'],
- watchdir.get('owner', 'localclient'), watchdir['path'],
- ])
+ self.store.append(
+ [
+ watchdir_id,
+ watchdir['enabled'],
+ 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'):
# Disable the remove and edit buttons, because nothing in the store is selected
diff --git a/deluge/plugins/AutoAdd/setup.py b/deluge/plugins/AutoAdd/setup.py
index 77ca16267..206ca7fe4 100644
--- a/deluge/plugins/AutoAdd/setup.py
+++ b/deluge/plugins/AutoAdd/setup.py
@@ -37,7 +37,6 @@ setup(
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -45,5 +44,6 @@ 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),
)
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/__init__.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/__init__.py
index bc9a8d82a..96ccc02ae 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/__init__.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/__init__.py
@@ -15,6 +15,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -22,6 +23,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -29,5 +31,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py
index 1d4fe9ae6..d42d90d2f 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/common.py
@@ -31,8 +31,10 @@ def raises_errors_as(error):
function to raise all exceptions as the specified error type.
"""
+
def decorator(func):
"""Returns a function which wraps the given func to raise all exceptions as error."""
+
@wraps(func)
def wrapper(self, *args, **kwargs):
"""Wraps the function in a try..except block and calls it with the specified args.
@@ -46,7 +48,9 @@ def raises_errors_as(error):
except Exception:
(value, tb) = exc_info()[1:]
six.reraise(error, value, tb)
+
return wrapper
+
return decorator
@@ -117,37 +121,37 @@ class IP(object):
def quadrants(self):
return (self.q1, self.q2, self.q3, self.q4)
-# def next_ip(self):
-# (q1, q2, q3, q4) = self.quadrants()
-# if q4 >= 255:
-# if q3 >= 255:
-# if q2 >= 255:
-# if q1 >= 255:
-# raise BadIP(_('There is not a next IP address'))
-# q1 += 1
-# else:
-# q2 += 1
-# else:
-# q3 += 1
-# else:
-# q4 += 1
-# return IP(q1, q2, q3, q4)
-#
-# def previous_ip(self):
-# (q1, q2, q3, q4) = self.quadrants()
-# if q4 <= 1:
-# if q3 <= 1:
-# if q2 <= 1:
-# if q1 <= 1:
-# raise BadIP(_('There is not a previous IP address'))
-# q1 -= 1
-# else:
-# q2 -= 1
-# else:
-# q3 -= 1
-# else:
-# q4 -= 1
-# return IP(q1, q2, q3, q4)
+ # def next_ip(self):
+ # (q1, q2, q3, q4) = self.quadrants()
+ # if q4 >= 255:
+ # if q3 >= 255:
+ # if q2 >= 255:
+ # if q1 >= 255:
+ # raise BadIP(_('There is not a next IP address'))
+ # q1 += 1
+ # else:
+ # q2 += 1
+ # else:
+ # q3 += 1
+ # else:
+ # q4 += 1
+ # return IP(q1, q2, q3, q4)
+ #
+ # def previous_ip(self):
+ # (q1, q2, q3, q4) = self.quadrants()
+ # if q4 <= 1:
+ # if q3 <= 1:
+ # if q2 <= 1:
+ # if q1 <= 1:
+ # raise BadIP(_('There is not a previous IP address'))
+ # q1 -= 1
+ # else:
+ # q2 -= 1
+ # else:
+ # q3 -= 1
+ # else:
+ # q4 -= 1
+ # return IP(q1, q2, q3, q4)
def __lt__(self, other):
if isinstance(other, ''.__class__):
@@ -166,5 +170,7 @@ 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,
)
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/core.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/core.py
index 18d0d036b..a096b8ac9 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/core.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/core.py
@@ -76,11 +76,15 @@ class Core(CorePluginBase):
self.file_progress = 0.0
self.core = component.get('Core')
- self.config = deluge.configmanager.ConfigManager('blocklist.conf', DEFAULT_PREFS)
+ self.config = deluge.configmanager.ConfigManager(
+ 'blocklist.conf', DEFAULT_PREFS
+ )
if 'whitelisted' not in self.config:
self.config['whitelisted'] = []
- self.reader = create_reader(self.config['list_type'], self.config['list_compression'])
+ self.reader = create_reader(
+ self.config['list_type'], self.config['list_compression']
+ )
if not isinstance(self.config['last_update'], float):
self.config.config['last_update'] = 0.0
@@ -91,10 +95,15 @@ class Core(CorePluginBase):
if self.config['last_update']:
last_update = datetime.fromtimestamp(self.config['last_update'])
check_period = timedelta(days=self.config['check_after_days'])
- if not self.config['last_update'] or last_update + check_period < datetime.now():
+ if (
+ not self.config['last_update']
+ or last_update + check_period < datetime.now()
+ ):
update_now = True
else:
- d = self.import_list(deluge.configmanager.get_config_dir('blocklist.cache'))
+ d = self.import_list(
+ deluge.configmanager.get_config_dir('blocklist.cache')
+ )
d.addCallbacks(self.on_import_complete, self.on_import_error)
if self.need_to_resume_session:
d.addBoth(self.resume_session)
@@ -104,14 +113,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 +198,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)
@@ -217,13 +226,16 @@ class Core(CorePluginBase):
if self.config['last_update']:
last_update = datetime.fromtimestamp(self.config['last_update'])
check_period = timedelta(days=self.config['check_after_days'])
- if not self.config['last_update'] or last_update + check_period < datetime.now():
+ if (
+ not self.config['last_update']
+ or last_update + check_period < datetime.now()
+ ):
update_now = True
if self.update_timer.running:
self.update_timer.stop()
if self.config['check_after_days'] > 0:
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]
@@ -232,7 +244,7 @@ class Core(CorePluginBase):
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.',
+ 'current blocklist and re-add whitelisted.'
)
self.has_imported = False
d = self.import_list(deluge.configmanager.get_config_dir('blocklist.cache'))
@@ -295,6 +307,7 @@ class Core(CorePluginBase):
Deferred: a Deferred which fires once the blocklist has been downloaded.
"""
+
def on_retrieve_data(data, current_length, total_length):
if total_length:
fp = current_length / total_length
@@ -306,6 +319,7 @@ class Core(CorePluginBase):
self.file_progress = fp
import socket
+
socket.setdefaulttimeout(self.config['timeout'])
if not url:
@@ -313,14 +327,18 @@ class Core(CorePluginBase):
headers = {}
if self.config['last_update'] and not self.force_download:
- headers['If-Modified-Since'] = formatdate(self.config['last_update'], usegmt=True)
+ headers['If-Modified-Since'] = formatdate(
+ self.config['last_update'], usegmt=True
+ )
log.debug('Attempting to download blocklist %s', url)
log.debug('Sending headers: %s', headers)
self.is_downloading = True
return download_file(
- url, deluge.configmanager.get_config_dir('blocklist.download'),
- on_retrieve_data, headers,
+ url,
+ deluge.configmanager.get_config_dir('blocklist.download'),
+ on_retrieve_data,
+ headers,
)
def on_download_complete(self, blocklist):
@@ -369,7 +387,8 @@ class Core(CorePluginBase):
if 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,
+ self.config['try_times'],
)
self.failed_attempts += 1
d = self.download_list()
@@ -430,7 +449,11 @@ class Core(CorePluginBase):
log.exception(failure)
log.debug('Importing using reader: %s', self.reader)
- log.debug('Reader type: %s compression: %s', self.config['list_type'], self.config['list_compression'])
+ log.debug(
+ 'Reader type: %s compression: %s',
+ self.config['list_type'],
+ self.config['list_compression'],
+ )
log.debug('Clearing current ip filtering')
# self.blocklist.add_rule('0.0.0.0', '255.255.255.255', ALLOW_RANGE)
d = threads.deferToThread(self.reader(blocklist).read, on_read_ip_range)
@@ -508,13 +531,21 @@ class Core(CorePluginBase):
"""
self.config['list_compression'] = detect_compression(blocklist)
- self.config['list_type'] = detect_format(blocklist, self.config['list_compression'])
- log.debug('Auto-detected type: %s compression: %s', self.config['list_type'], self.config['list_compression'])
+ self.config['list_type'] = detect_format(
+ blocklist, self.config['list_compression']
+ )
+ log.debug(
+ 'Auto-detected type: %s compression: %s',
+ self.config['list_type'],
+ self.config['list_compression'],
+ )
if not self.config['list_type']:
self.config['list_compression'] = ''
raise UnknownFormatError
else:
- self.reader = create_reader(self.config['list_type'], self.config['list_compression'])
+ self.reader = create_reader(
+ self.config['list_type'], self.config['list_compression']
+ )
def pause_session(self):
self.need_to_resume_session = not self.core.session.is_paused()
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/decompressers.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/decompressers.py
index 8b9a0f4fb..35211b706 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/decompressers.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/decompressers.py
@@ -17,25 +17,31 @@ import zipfile
def Zipped(reader): # NOQA: N802
"""Blocklist reader for zipped blocklists"""
+
def _open(self):
z = zipfile.ZipFile(self.file)
f = z.open(z.namelist()[0])
return f
+
reader.open = _open
return reader
def GZipped(reader): # NOQA: N802
"""Blocklist reader for gzipped blocklists"""
+
def _open(self):
return gzip.open(self.file)
+
reader.open = _open
return reader
def BZipped2(reader): # NOQA: N802
"""Blocklist reader for bzipped2 blocklists"""
+
def _open(self):
return bz2.BZ2File(self.file)
+
reader.open = _open
return reader
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/detect.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/detect.py
index 1d8b5d864..9ed960adb 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/detect.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/detect.py
@@ -12,17 +12,9 @@ from __future__ import unicode_literals
from .decompressers import BZipped2, GZipped, Zipped
from .readers import EmuleReader, PeerGuardianReader, SafePeerReader
-COMPRESSION_TYPES = {
- 'PK': 'Zip',
- '\x1f\x8b': 'GZip',
- 'BZ': 'BZip2',
-}
+COMPRESSION_TYPES = {'PK': 'Zip', '\x1f\x8b': 'GZip', 'BZ': 'BZip2'}
-DECOMPRESSERS = {
- 'Zip': Zipped,
- 'GZip': GZipped,
- 'BZip2': BZipped2,
-}
+DECOMPRESSERS = {'Zip': Zipped, 'GZip': GZipped, 'BZip2': BZipped2}
READERS = {
'Emule': EmuleReader,
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/gtkui.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/gtkui.py
index 3d5df6c41..ad73a45e6 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/gtkui.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/gtkui.py
@@ -67,9 +67,11 @@ 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_text('Downloading %.2f%%' % (status['file_progress'] * 100))
self.progress_bar.set_fraction(status['file_progress'])
self.progress_bar.show()
@@ -79,9 +81,7 @@ class GtkUI(GtkPluginBase):
self.builder.get_object('button_force_download').set_sensitive(False)
self.builder.get_object('image_up_to_date').hide()
- self.status_item.set_text(
- 'Importing ' + str(status['num_blocked']),
- )
+ self.status_item.set_text('Importing ' + str(status['num_blocked']))
self.progress_bar.set_text('Importing %s' % (status['num_blocked']))
self.progress_bar.pulse()
self.progress_bar.show()
@@ -99,15 +99,13 @@ 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'],
- )
+ self.builder.get_object('label_url').set_text(status['file_url'])
client.blocklist.get_status().addCallback(_on_get_status)
@@ -115,8 +113,12 @@ class GtkUI(GtkPluginBase):
def _on_get_config(config):
log.trace('Loaded config: %s', config)
self.builder.get_object('entry_url').set_text(config['url'])
- self.builder.get_object('spin_check_days').set_value(config['check_after_days'])
- self.builder.get_object('chk_import_on_start').set_active(config['load_on_start'])
+ self.builder.get_object('spin_check_days').set_value(
+ config['check_after_days']
+ )
+ self.builder.get_object('chk_import_on_start').set_active(
+ config['load_on_start']
+ )
self.populate_whitelist(config['whitelisted'])
client.blocklist.get_config().addCallback(_on_get_config)
@@ -124,9 +126,15 @@ class GtkUI(GtkPluginBase):
def _on_apply_prefs(self):
config = {}
config['url'] = self.builder.get_object('entry_url').get_text().strip()
- config['check_after_days'] = self.builder.get_object('spin_check_days').get_value_as_int()
- config['load_on_start'] = self.builder.get_object('chk_import_on_start').get_active()
- config['whitelisted'] = [ip[0] for ip in self.whitelist_model if ip[0] != 'IP HERE']
+ config['check_after_days'] = self.builder.get_object(
+ 'spin_check_days'
+ ).get_value_as_int()
+ config['load_on_start'] = self.builder.get_object(
+ 'chk_import_on_start'
+ ).get_active()
+ config['whitelisted'] = [
+ ip[0] for ip in self.whitelist_model if ip[0] != 'IP HERE'
+ ]
client.blocklist.set_config(config)
def _on_button_check_download_clicked(self, widget):
@@ -157,26 +165,28 @@ class GtkUI(GtkPluginBase):
# Create the whitelisted model
self.build_whitelist_model_treeview()
- 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,
- ),
- })
+ 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,
+ ),
+ }
+ )
# 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
@@ -184,15 +194,14 @@ class GtkUI(GtkPluginBase):
# Add the page to the preferences dialog
self.plugin.add_preferences_page(
- _('Blocklist'),
- self.builder.get_object('blocklist_prefs_box'),
+ _('Blocklist'), 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()
@@ -213,21 +222,16 @@ class GtkUI(GtkPluginBase):
except common.BadIP as ex:
model.remove(model.get_iter_from_string(path_string))
from deluge.ui.gtkui import dialogs
+
d = dialogs.ErrorDialog(_('Bad IP address'), ex.message)
d.run()
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()
@@ -243,6 +247,4 @@ class GtkUI(GtkPluginBase):
def populate_whitelist(self, whitelist):
self.whitelist_model.clear()
for ip in whitelist:
- self.whitelist_model.set(
- self.whitelist_model.append(), 0, ip, 1, True,
- )
+ self.whitelist_model.set(self.whitelist_model.append(), 0, ip, 1, True)
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/peerguardian.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/peerguardian.py
index cf5675ca8..ba410c2cf 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/peerguardian.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/peerguardian.py
@@ -24,7 +24,6 @@ class PGException(Exception):
# Incrementally reads PeerGuardian blocklists v1 and v2.
# See http://wiki.phoenixlabs.org/wiki/P2B_Format
class PGReader(object):
-
def __init__(self, filename):
log.debug('PGReader loading: %s', filename)
diff --git a/deluge/plugins/Blocklist/deluge/plugins/blocklist/readers.py b/deluge/plugins/Blocklist/deluge/plugins/blocklist/readers.py
index 2a57efff5..4079e849e 100644
--- a/deluge/plugins/Blocklist/deluge/plugins/blocklist/readers.py
+++ b/deluge/plugins/Blocklist/deluge/plugins/blocklist/readers.py
@@ -25,6 +25,7 @@ class ReaderParseError(Exception):
class BaseReader(object):
"""Base reader for blocklist files"""
+
def __init__(self, _file):
"""Creates a new BaseReader given a file"""
self.file = _file
@@ -60,8 +61,9 @@ class BaseReader(object):
if not self.is_ignored(line):
try:
(start, end) = self.parse(line)
- if not re.match(r'^(\d{1,3}\.){4}$', start + '.') or \
- not re.match(r'^(\d{1,3}\.){4}$', end + '.'):
+ if not re.match(r'^(\d{1,3}\.){4}$', start + '.') or not re.match(
+ r'^(\d{1,3}\.){4}$', end + '.'
+ ):
valid = False
except Exception:
valid = False
@@ -82,16 +84,19 @@ class BaseReader(object):
class EmuleReader(BaseReader):
"""Blocklist reader for emule style blocklists"""
+
def parse(self, line):
return line.strip().split(' , ')[0].split(' - ')
class SafePeerReader(BaseReader):
"""Blocklist reader for SafePeer style blocklists"""
+
def parse(self, line):
return line.strip().split(':')[-1].split('-')
class PeerGuardianReader(SafePeerReader):
"""Blocklist reader for PeerGuardian style blocklists"""
+
pass
diff --git a/deluge/plugins/Blocklist/setup.py b/deluge/plugins/Blocklist/setup.py
index 03e2e189d..6d7f01253 100644
--- a/deluge/plugins/Blocklist/setup.py
+++ b/deluge/plugins/Blocklist/setup.py
@@ -39,5 +39,6 @@ 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),
)
diff --git a/deluge/plugins/Execute/deluge/plugins/execute/__init__.py b/deluge/plugins/Execute/deluge/plugins/execute/__init__.py
index f7854eeb7..c6d55f4ec 100644
--- a/deluge/plugins/Execute/deluge/plugins/execute/__init__.py
+++ b/deluge/plugins/Execute/deluge/plugins/execute/__init__.py
@@ -15,6 +15,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -22,6 +23,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -29,5 +31,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Execute/deluge/plugins/execute/core.py b/deluge/plugins/Execute/deluge/plugins/execute/core.py
index ed35a32bf..c7824e5f0 100644
--- a/deluge/plugins/Execute/deluge/plugins/execute/core.py
+++ b/deluge/plugins/Execute/deluge/plugins/execute/core.py
@@ -25,9 +25,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
-DEFAULT_CONFIG = {
- 'commands': [],
-}
+DEFAULT_CONFIG = {'commands': []}
EXECUTE_ID = 0
EXECUTE_EVENT = 1
@@ -44,6 +42,7 @@ class ExecuteCommandAddedEvent(DelugeEvent):
"""
Emitted when a new command is added.
"""
+
def __init__(self, command_id, event, command):
self._args = [command_id, event, command]
@@ -52,6 +51,7 @@ class ExecuteCommandRemovedEvent(DelugeEvent):
"""
Emitted when a command is removed.
"""
+
def __init__(self, command_id):
self._args = [command_id]
@@ -72,11 +72,15 @@ class Core(CorePluginBase):
def create_event_handler(event):
def event_handler(torrent_id, *arg):
self.execute_commands(torrent_id, event, *arg)
+
return event_handler
+
event_handler = create_event_handler(event)
event_manager.register_event_handler(EVENT_MAP[event], event_handler)
if event == 'removed':
- event_manager.register_event_handler('PreTorrentRemovedEvent', self.on_preremoved)
+ event_manager.register_event_handler(
+ 'PreTorrentRemovedEvent', self.on_preremoved
+ )
self.registered_events[event] = event_handler
log.debug('Execute core plugin enabled!')
@@ -85,14 +89,20 @@ class Core(CorePluginBase):
# Get and store the torrent info before it is removed
torrent = component.get('TorrentManager').torrents[torrent_id]
info = torrent.get_status(['name', 'download_location'])
- self.preremoved_cache[torrent_id] = [torrent_id, info['name'], info['download_location']]
+ self.preremoved_cache[torrent_id] = [
+ torrent_id,
+ info['name'],
+ info['download_location'],
+ ]
def execute_commands(self, torrent_id, event, *arg):
if event == 'added' and arg[0]:
# No futher action as from_state (arg[0]) is True
return
elif event == 'removed':
- torrent_id, torrent_name, download_location = self.preremoved_cache.pop(torrent_id)
+ torrent_id, torrent_name, download_location = self.preremoved_cache.pop(
+ torrent_id
+ )
else:
torrent = component.get('TorrentManager').torrents[torrent_id]
info = torrent.get_status(['name', 'download_location'])
@@ -119,7 +129,8 @@ class Core(CorePluginBase):
command = os.path.expanduser(command)
cmd_args = [
- torrent_id.encode('utf8'), torrent_name.encode('utf8'),
+ torrent_id.encode('utf8'),
+ torrent_name.encode('utf8'),
download_location.encode('utf8'),
]
if windows_check():
@@ -146,7 +157,9 @@ class Core(CorePluginBase):
command_id = hashlib.sha1(str(time.time())).hexdigest()
self.config['commands'].append((command_id, event, command))
self.config.save()
- component.get('EventManager').emit(ExecuteCommandAddedEvent(command_id, event, command))
+ component.get('EventManager').emit(
+ ExecuteCommandAddedEvent(command_id, event, command)
+ )
@export
def get_commands(self):
@@ -157,7 +170,9 @@ class Core(CorePluginBase):
for command in self.config['commands']:
if command[EXECUTE_ID] == command_id:
self.config['commands'].remove(command)
- component.get('EventManager').emit(ExecuteCommandRemovedEvent(command_id))
+ component.get('EventManager').emit(
+ ExecuteCommandRemovedEvent(command_id)
+ )
break
self.config.save()
diff --git a/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py b/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py
index f74e72007..a2b4f5f68 100644
--- a/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py
+++ b/deluge/plugins/Execute/deluge/plugins/execute/gtkui.py
@@ -55,14 +55,20 @@ class ExecutePreferences(object):
events.set_model(store)
events.set_active(0)
- self.plugin.add_preferences_page(_('Execute'), self.builder.get_object('execute_box'))
+ self.plugin.add_preferences_page(
+ _('Execute'), self.builder.get_object('execute_box')
+ )
self.plugin.register_hook('on_show_prefs', self.load_commands)
self.plugin.register_hook('on_apply_prefs', self.on_apply_prefs)
self.load_commands()
- client.register_event_handler('ExecuteCommandAddedEvent', self.on_command_added_event)
- client.register_event_handler('ExecuteCommandRemovedEvent', self.on_command_removed_event)
+ client.register_event_handler(
+ 'ExecuteCommandAddedEvent', self.on_command_added_event
+ )
+ client.register_event_handler(
+ 'ExecuteCommandRemovedEvent', self.on_command_removed_event
+ )
def unload(self):
self.plugin.remove_preferences_page(_('Execute'))
@@ -145,7 +151,6 @@ class ExecutePreferences(object):
class GtkUI(GtkPluginBase):
-
def enable(self):
self.plugin = component.get('PluginManager')
self.preferences = ExecutePreferences(self.plugin)
diff --git a/deluge/plugins/Execute/setup.py b/deluge/plugins/Execute/setup.py
index 55d0ed56b..5bee45635 100644
--- a/deluge/plugins/Execute/setup.py
+++ b/deluge/plugins/Execute/setup.py
@@ -28,11 +28,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -40,5 +38,6 @@ 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),
)
diff --git a/deluge/plugins/Extractor/deluge/plugins/extractor/__init__.py b/deluge/plugins/Extractor/deluge/plugins/extractor/__init__.py
index 7d3492d2c..6db72b63b 100644
--- a/deluge/plugins/Extractor/deluge/plugins/extractor/__init__.py
+++ b/deluge/plugins/Extractor/deluge/plugins/extractor/__init__.py
@@ -19,6 +19,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -26,6 +27,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -33,5 +35,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Extractor/deluge/plugins/extractor/core.py b/deluge/plugins/Extractor/deluge/plugins/extractor/core.py
index dbedb23e8..99d1b083a 100644
--- a/deluge/plugins/Extractor/deluge/plugins/extractor/core.py
+++ b/deluge/plugins/Extractor/deluge/plugins/extractor/core.py
@@ -28,10 +28,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
-DEFAULT_PREFS = {
- 'extract_path': '',
- 'use_name_folder': True,
-}
+DEFAULT_PREFS = {'extract_path': '', 'use_name_folder': True}
if windows_check():
win_7z_exes = [
@@ -61,10 +58,7 @@ if windows_check():
# ".tar.bz2", ".tbz",
# ".tar.lzma", ".tlz",
# ".tar.xz", ".txz",
- exts_7z = [
- '.rar', '.zip', '.tar',
- '.7z', '.xz', '.lzma',
- ]
+ exts_7z = ['.rar', '.zip', '.tar', '.7z', '.xz', '.lzma']
for win_7z_exe in win_7z_exes:
if which(win_7z_exe):
EXTRACT_COMMANDS = dict.fromkeys(exts_7z, [win_7z_exe, switch_7z])
@@ -82,10 +76,14 @@ else:
'.rar': ['unrar', 'x -o+ -y'],
'.tar': ['tar', '-xf'],
'.zip': ['unzip', ''],
- '.tar.gz': ['tar', '-xzf'], '.tgz': ['tar', '-xzf'],
- '.tar.bz2': ['tar', '-xjf'], '.tbz': ['tar', '-xjf'],
- '.tar.lzma': ['tar', '--lzma -xf'], '.tlz': ['tar', '--lzma -xf'],
- '.tar.xz': ['tar', '--xz -xf'], '.txz': ['tar', '--xz -xf'],
+ '.tar.gz': ['tar', '-xzf'],
+ '.tgz': ['tar', '-xzf'],
+ '.tar.bz2': ['tar', '-xjf'],
+ '.tbz': ['tar', '-xjf'],
+ '.tar.lzma': ['tar', '--lzma -xf'],
+ '.tlz': ['tar', '--lzma -xf'],
+ '.tar.xz': ['tar', '--xz -xf'],
+ '.txz': ['tar', '--xz -xf'],
'.7z': ['7zr', 'x'],
}
# Test command exists and if not, remove.
@@ -102,13 +100,21 @@ if not EXTRACT_COMMANDS:
class Core(CorePluginBase):
def enable(self):
- self.config = deluge.configmanager.ConfigManager('extractor.conf', DEFAULT_PREFS)
+ self.config = deluge.configmanager.ConfigManager(
+ 'extractor.conf', DEFAULT_PREFS
+ )
if not self.config['extract_path']:
- self.config['extract_path'] = deluge.configmanager.ConfigManager('core.conf')['download_location']
- component.get('EventManager').register_event_handler('TorrentFinishedEvent', self._on_torrent_finished)
+ self.config['extract_path'] = deluge.configmanager.ConfigManager(
+ 'core.conf'
+ )['download_location']
+ component.get('EventManager').register_event_handler(
+ 'TorrentFinishedEvent', self._on_torrent_finished
+ )
def disable(self):
- component.get('EventManager').deregister_event_handler('TorrentFinishedEvent', self._on_torrent_finished)
+ component.get('EventManager').deregister_event_handler(
+ 'TorrentFinishedEvent', self._on_torrent_finished
+ )
def update(self):
pass
@@ -136,7 +142,9 @@ class Core(CorePluginBase):
continue
cmd = EXTRACT_COMMANDS[file_ext]
- fpath = os.path.join(tid_status['download_location'], os.path.normpath(f['path']))
+ fpath = os.path.join(
+ tid_status['download_location'], os.path.normpath(f['path'])
+ )
dest = os.path.normpath(self.config['extract_path'])
if self.config['use_name_folder']:
dest = os.path.join(dest, tid_status['name'])
@@ -153,11 +161,22 @@ class Core(CorePluginBase):
if not result[2]:
log.info('Extract successful: %s (%s)', fpath, torrent_id)
else:
- log.error('Extract failed: %s (%s) %s', fpath, torrent_id, result[1])
+ log.error(
+ 'Extract failed: %s (%s) %s', fpath, torrent_id, result[1]
+ )
# Run the command and add callback.
- log.debug('Extracting %s from %s with %s %s to %s', fpath, torrent_id, cmd[0], cmd[1], dest)
- d = getProcessOutputAndValue(cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest))
+ log.debug(
+ 'Extracting %s from %s with %s %s to %s',
+ fpath,
+ torrent_id,
+ cmd[0],
+ cmd[1],
+ dest,
+ )
+ d = getProcessOutputAndValue(
+ cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest)
+ )
d.addCallback(on_extract, torrent_id, fpath)
@export
diff --git a/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py b/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py
index 2adea4368..aaae29a93 100644
--- a/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py
+++ b/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py
@@ -31,15 +31,25 @@ class GtkUI(GtkPluginBase):
self.builder = gtk.Builder()
self.builder.add_from_file(get_resource('extractor_prefs.ui'))
- component.get('Preferences').add_page(_('Extractor'), self.builder.get_object('extractor_prefs_box'))
- component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
+ component.get('Preferences').add_page(
+ _('Extractor'), self.builder.get_object('extractor_prefs_box')
+ )
+ component.get('PluginManager').register_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').register_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
self.on_show_prefs()
def disable(self):
component.get('Preferences').remove_page(_('Extractor'))
- component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
+ component.get('PluginManager').deregister_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').deregister_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
del self.builder
def on_apply_prefs(self):
@@ -66,10 +76,14 @@ class GtkUI(GtkPluginBase):
def on_get_config(config):
if client.is_localhost():
- self.builder.get_object('folderchooser_path').set_current_folder(config['extract_path'])
+ self.builder.get_object('folderchooser_path').set_current_folder(
+ config['extract_path']
+ )
else:
self.builder.get_object('entry_path').set_text(config['extract_path'])
- self.builder.get_object('chk_use_name').set_active(config['use_name_folder'])
+ self.builder.get_object('chk_use_name').set_active(
+ config['use_name_folder']
+ )
client.extractor.get_config().addCallback(on_get_config)
diff --git a/deluge/plugins/Extractor/setup.py b/deluge/plugins/Extractor/setup.py
index 9be0652a7..7426c690a 100644
--- a/deluge/plugins/Extractor/setup.py
+++ b/deluge/plugins/Extractor/setup.py
@@ -41,11 +41,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -53,5 +51,6 @@ 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),
)
diff --git a/deluge/plugins/Label/deluge/plugins/label/__init__.py b/deluge/plugins/Label/deluge/plugins/label/__init__.py
index 363d49d42..bc0b0f243 100644
--- a/deluge/plugins/Label/deluge/plugins/label/__init__.py
+++ b/deluge/plugins/Label/deluge/plugins/label/__init__.py
@@ -19,6 +19,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -26,6 +27,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -33,5 +35,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Label/deluge/plugins/label/core.py b/deluge/plugins/Label/deluge/plugins/label/core.py
index 4a1976edd..b16156c91 100644
--- a/deluge/plugins/Label/deluge/plugins/label/core.py
+++ b/deluge/plugins/Label/deluge/plugins/label/core.py
@@ -73,6 +73,7 @@ class Core(CorePluginBase):
self.labels = {label_id:label_options_dict}
self.torrent_labels = {torrent_id:label_id}
"""
+
def enable(self):
log.info('*** Start Label plugin ***')
self.plugin = component.get('CorePluginManager')
@@ -90,19 +91,29 @@ class Core(CorePluginBase):
self.clean_initial_config()
- component.get('EventManager').register_event_handler('TorrentAddedEvent', self.post_torrent_add)
- component.get('EventManager').register_event_handler('TorrentRemovedEvent', self.post_torrent_remove)
+ component.get('EventManager').register_event_handler(
+ 'TorrentAddedEvent', self.post_torrent_add
+ )
+ component.get('EventManager').register_event_handler(
+ 'TorrentRemovedEvent', self.post_torrent_remove
+ )
# register tree:
- component.get('FilterManager').register_tree_field('label', self.init_filter_dict)
+ component.get('FilterManager').register_tree_field(
+ 'label', self.init_filter_dict
+ )
log.debug('Label plugin enabled..')
def disable(self):
self.plugin.deregister_status_field('label')
component.get('FilterManager').deregister_tree_field('label')
- component.get('EventManager').deregister_event_handler('TorrentAddedEvent', self.post_torrent_add)
- component.get('EventManager').deregister_event_handler('TorrentRemovedEvent', self.post_torrent_remove)
+ component.get('EventManager').deregister_event_handler(
+ 'TorrentAddedEvent', self.post_torrent_add
+ )
+ component.get('EventManager').deregister_event_handler(
+ 'TorrentRemovedEvent', self.post_torrent_remove
+ )
def update(self):
pass
@@ -169,7 +180,9 @@ class Core(CorePluginBase):
see label_set_options for more options.
"""
label_id = label_id.lower()
- check_input(RE_VALID.match(label_id), _('Invalid label, valid characters:[a-z0-9_-]'))
+ check_input(
+ RE_VALID.match(label_id), _('Invalid label, valid characters:[a-z0-9_-]')
+ )
check_input(label_id, _('Empty Label'))
check_input(not (label_id in self.labels), _('Label already exists'))
@@ -209,7 +222,7 @@ class Core(CorePluginBase):
{
'move_completed': options['move_completed'],
'move_completed_path': options['move_completed_path'],
- },
+ }
)
def _unset_torrent_options(self, torrent_id, label_id):
@@ -217,11 +230,21 @@ class Core(CorePluginBase):
torrent = self.torrents[torrent_id]
if options['apply_max']:
- torrent.set_max_download_speed(self.core_cfg.config['max_download_speed_per_torrent'])
- torrent.set_max_upload_speed(self.core_cfg.config['max_upload_speed_per_torrent'])
- torrent.set_max_connections(self.core_cfg.config['max_connections_per_torrent'])
- torrent.set_max_upload_slots(self.core_cfg.config['max_upload_slots_per_torrent'])
- torrent.set_prioritize_first_last_pieces(self.core_cfg.config['prioritize_first_last_pieces'])
+ torrent.set_max_download_speed(
+ self.core_cfg.config['max_download_speed_per_torrent']
+ )
+ torrent.set_max_upload_speed(
+ self.core_cfg.config['max_upload_speed_per_torrent']
+ )
+ torrent.set_max_connections(
+ self.core_cfg.config['max_connections_per_torrent']
+ )
+ torrent.set_max_upload_slots(
+ self.core_cfg.config['max_upload_slots_per_torrent']
+ )
+ torrent.set_prioritize_first_last_pieces(
+ self.core_cfg.config['prioritize_first_last_pieces']
+ )
if options['apply_queue']:
torrent.set_auto_managed(self.core_cfg.config['auto_managed'])
@@ -234,7 +257,7 @@ class Core(CorePluginBase):
{
'move_completed': self.core_cfg.config['move_completed'],
'move_completed_path': self.core_cfg.config['move_completed_path'],
- },
+ }
)
def _has_auto_match(self, torrent, label_options):
@@ -311,8 +334,7 @@ class Core(CorePluginBase):
def get_config(self):
"""see : label_set_config"""
return {
- key: self.config[key]
- for key in CORE_OPTIONS if key in self.config.config
+ key: self.config[key] for key in CORE_OPTIONS if key in self.config.config
}
@export
diff --git a/deluge/plugins/Label/deluge/plugins/label/gtkui/label_config.py b/deluge/plugins/Label/deluge/plugins/label/gtkui/label_config.py
index f5a03d564..507be5afa 100644
--- a/deluge/plugins/Label/deluge/plugins/label/gtkui/label_config.py
+++ b/deluge/plugins/Label/deluge/plugins/label/gtkui/label_config.py
@@ -33,7 +33,9 @@ class LabelConfig(object):
builder = Builder()
builder.add_from_file(get_resource('label_pref.ui'))
- self.plugin.add_preferences_page(_('Label'), builder.get_object('label_prefs_box'))
+ self.plugin.add_preferences_page(
+ _('Label'), builder.get_object('label_prefs_box')
+ )
self.plugin.register_hook('on_show_prefs', self.load_settings)
self.plugin.register_hook('on_apply_prefs', self.on_apply_prefs)
diff --git a/deluge/plugins/Label/deluge/plugins/label/gtkui/sidebar_menu.py b/deluge/plugins/Label/deluge/plugins/label/gtkui/sidebar_menu.py
index cdb298ccb..d143c7a7e 100644
--- a/deluge/plugins/Label/deluge/plugins/label/gtkui/sidebar_menu.py
+++ b/deluge/plugins/Label/deluge/plugins/label/gtkui/sidebar_menu.py
@@ -80,7 +80,7 @@ class LabelSidebarMenu(object):
for item in self.items:
item.show()
# default items
- sensitive = ((label not in (NO_LABEL, None, '', 'All')) and (cat != 'cat'))
+ sensitive = (label not in (NO_LABEL, None, '', 'All')) and (cat != 'cat')
for item in self.items:
item.set_sensitive(sensitive)
@@ -127,13 +127,28 @@ 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',
+ 'apply_max',
+ 'apply_queue',
+ 'stop_at_ratio',
+ 'apply_queue',
+ 'remove_at_ratio',
+ 'apply_move_completed',
+ 'move_completed',
+ 'is_auto_managed',
+ 'auto_add',
]
# list of tuples, because order matters when nesting.
sensitive_groups = [
- ('apply_max', ['max_download_speed', 'max_upload_speed', 'max_upload_slots', 'max_connections']),
+ (
+ 'apply_max',
+ [
+ 'max_download_speed',
+ 'max_upload_speed',
+ 'max_upload_slots',
+ 'max_connections',
+ ],
+ ),
('apply_queue', ['is_auto_managed', 'stop_at_ratio']),
('stop_at_ratio', ['remove_at_ratio', 'stop_ratio']), # nested
('apply_move_completed', ['move_completed']),
@@ -152,7 +167,9 @@ class OptionsDialog(object):
self.dialog.set_transient_for(component.get('MainWindow').window)
self.builder.connect_signals(self)
# Show the label name in the header label
- self.builder.get_object('label_header').set_markup('<b>%s:</b> %s' % (_('Label Options'), self.label))
+ self.builder.get_object('label_header').set_markup(
+ '<b>%s:</b> %s' % (_('Label Options'), self.label)
+ )
for chk_id, group in self.sensitive_groups:
chk = self.builder.get_object(chk_id)
@@ -171,15 +188,21 @@ class OptionsDialog(object):
self.builder.get_object(chk_id).set_active(bool(options[chk_id]))
if client.is_localhost():
- self.builder.get_object('move_completed_path').set_filename(options['move_completed_path'])
+ self.builder.get_object('move_completed_path').set_filename(
+ options['move_completed_path']
+ )
self.builder.get_object('move_completed_path').show()
self.builder.get_object('move_completed_path_entry').hide()
else:
- self.builder.get_object('move_completed_path_entry').set_text(options['move_completed_path'])
+ self.builder.get_object('move_completed_path_entry').set_text(
+ options['move_completed_path']
+ )
self.builder.get_object('move_completed_path_entry').show()
self.builder.get_object('move_completed_path').hide()
- self.builder.get_object('auto_add_trackers').get_buffer().set_text('\n'.join(options['auto_add_trackers']))
+ self.builder.get_object('auto_add_trackers').get_buffer().set_text(
+ '\n'.join(options['auto_add_trackers'])
+ )
self.apply_sensitivity()
@@ -190,18 +213,32 @@ class OptionsDialog(object):
for spin_id in self.spin_ids:
options[spin_id] = self.builder.get_object(spin_id).get_value()
for spin_int_id in self.spin_int_ids:
- options[spin_int_id] = self.builder.get_object(spin_int_id).get_value_as_int()
+ options[spin_int_id] = self.builder.get_object(
+ spin_int_id
+ ).get_value_as_int()
for chk_id in self.chk_ids:
options[chk_id] = self.builder.get_object(chk_id).get_active()
if client.is_localhost():
- options['move_completed_path'] = self.builder.get_object('move_completed_path').get_filename()
+ options['move_completed_path'] = self.builder.get_object(
+ 'move_completed_path'
+ ).get_filename()
else:
- options['move_completed_path'] = self.builder.get_object('move_completed_path_entry').get_text()
-
- buff = self.builder.get_object('auto_add_trackers').get_buffer() # sometimes I hate gtk...
- tracker_lst = buff.get_text(buff.get_start_iter(), buff.get_end_iter()).strip().split('\n')
- options['auto_add_trackers'] = [x for x in tracker_lst if x] # filter out empty lines.
+ options['move_completed_path'] = self.builder.get_object(
+ 'move_completed_path_entry'
+ ).get_text()
+
+ buff = self.builder.get_object(
+ 'auto_add_trackers'
+ ).get_buffer() # sometimes I hate gtk...
+ tracker_lst = (
+ buff.get_text(buff.get_start_iter(), buff.get_end_iter())
+ .strip()
+ .split('\n')
+ )
+ options['auto_add_trackers'] = [
+ x for x in tracker_lst if x
+ ] # filter out empty lines.
log.debug(options)
client.label.set_options(self.label, options)
diff --git a/deluge/plugins/Label/setup.py b/deluge/plugins/Label/setup.py
index a0c048416..c20705a69 100644
--- a/deluge/plugins/Label/setup.py
+++ b/deluge/plugins/Label/setup.py
@@ -32,11 +32,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -44,5 +42,6 @@ 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),
)
diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/__init__.py b/deluge/plugins/Notifications/deluge/plugins/notifications/__init__.py
index 0164464c8..810e284df 100644
--- a/deluge/plugins/Notifications/deluge/plugins/notifications/__init__.py
+++ b/deluge/plugins/Notifications/deluge/plugins/notifications/__init__.py
@@ -20,6 +20,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -27,6 +28,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -34,5 +36,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/common.py b/deluge/plugins/Notifications/deluge/plugins/notifications/common.py
index 5d6029cc1..8284d9700 100644
--- a/deluge/plugins/Notifications/deluge/plugins/notifications/common.py
+++ b/deluge/plugins/Notifications/deluge/plugins/notifications/common.py
@@ -27,18 +27,14 @@ log = logging.getLogger(__name__)
def get_resource(filename):
- return resource_filename('deluge.plugins.notifications', os.path.join('data', filename))
+ return resource_filename(
+ 'deluge.plugins.notifications', os.path.join('data', filename)
+ )
class CustomNotifications(object):
-
def __init__(self, plugin_name=None):
- self.custom_notifications = {
- 'email': {},
- 'popup': {},
- 'blink': {},
- 'sound': {},
- }
+ self.custom_notifications = {'email': {}, 'popup': {}, 'blink': {}, 'sound': {}}
def enable(self):
pass
@@ -50,7 +46,13 @@ class CustomNotifications(object):
self._deregister_custom_provider(kind, eventtype)
def _handle_custom_providers(self, kind, eventtype, *args, **kwargs):
- log.debug('Calling CORE custom %s providers for %s: %s %s', kind, eventtype, args, kwargs)
+ log.debug(
+ 'Calling CORE custom %s providers for %s: %s %s',
+ kind,
+ eventtype,
+ args,
+ kwargs,
+ )
if eventtype in self.config['subscriptions'][kind]:
wrapper, handler = self.custom_notifications[kind][eventtype]
log.debug('Found handler for kind %s: %s', kind, handler)
@@ -65,17 +67,18 @@ class CustomNotifications(object):
if not self._handled_eventtype(eventtype, handler):
return defer.succeed('Event not handled')
if eventtype not in self.custom_notifications:
+
def wrapper(*args, **kwargs):
return self._handle_custom_providers(kind, eventtype, *args, **kwargs)
+
self.custom_notifications[kind][eventtype] = (wrapper, handler)
else:
wrapper, handler = self.custom_notifications[kind][eventtype]
try:
- component.get('EventManager').register_event_handler(
- eventtype, wrapper,
- )
+ component.get('EventManager').register_event_handler(eventtype, wrapper)
except KeyError:
from deluge.ui.client import client
+
client.register_event_handler(eventtype, wrapper)
def _deregister_custom_provider(self, kind, eventtype):
@@ -83,10 +86,11 @@ 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
+
client.deregister_event_handler(eventtype, wrapper)
self.custom_notifications[kind].pop(eventtype)
except KeyError:
@@ -101,7 +105,7 @@ class CustomNotifications(object):
return True
log.error(
'You cannot register custom notification providers '
- 'for built-in event types.',
+ 'for built-in event types.'
)
return False
return True
diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/core.py b/deluge/plugins/Notifications/deluge/plugins/notifications/core.py
index 66c3ee078..123f9cf05 100644
--- a/deluge/plugins/Notifications/deluge/plugins/notifications/core.py
+++ b/deluge/plugins/Notifications/deluge/plugins/notifications/core.py
@@ -40,22 +40,18 @@ DEFAULT_PREFS = {
'smtp_tls': False, # SSL or TLS
'smtp_recipients': [],
# Subscriptions
- 'subscriptions': {
- 'email': [],
- },
+ 'subscriptions': {'email': []},
}
class CoreNotifications(CustomNotifications):
-
def __init__(self, plugin_name=None):
CustomNotifications.__init__(self, plugin_name)
def enable(self):
CustomNotifications.enable(self)
self.register_custom_email_notification(
- 'TorrentFinishedEvent',
- self._on_torrent_finished_event,
+ 'TorrentFinishedEvent', self._on_torrent_finished_event
)
def disable(self):
@@ -80,8 +76,7 @@ class CoreNotifications(CustomNotifications):
return defer.succeed('SMTP notification not enabled.')
subject, message = result
log.debug(
- 'Spawning new thread to send email with subject: %s: %s',
- subject, message,
+ '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.
@@ -109,20 +104,25 @@ class CoreNotifications(CustomNotifications):
'smtp_recipients': to_addrs_str,
'date': formatdate(),
}
- headers = """\
+ headers = (
+ """\
From: %(smtp_from)s
To: %(smtp_recipients)s
Subject: %(subject)s
Date: %(date)s
-""" % headers_dict
+"""
+ % headers_dict
+ )
message = '\r\n'.join((headers + message).splitlines())
try:
# Python 2.6
- server = smtplib.SMTP(self.config['smtp_host'], self.config['smtp_port'], timeout=60)
+ server = smtplib.SMTP(
+ self.config['smtp_host'], self.config['smtp_port'], timeout=60
+ )
except Exception as ex:
err_msg = _('There was an error sending the notification email: %s') % ex
log.error(err_msg)
@@ -154,7 +154,9 @@ Date: %(date)s
try:
server.sendmail(self.config['smtp_from'], to_addrs, message)
except smtplib.SMTPException as ex:
- err_msg = _('There was an error sending the notification email: %s') % ex
+ err_msg = (
+ _('There was an error sending the notification email: %s') % ex
+ )
log.error(err_msg)
return ex
finally:
@@ -162,6 +164,7 @@ Date: %(date)s
# avoid false failure detection when the server closes
# the SMTP connection with TLS enabled
import socket
+
try:
server.quit()
except socket.sslerror:
@@ -176,13 +179,16 @@ Date: %(date)s
torrent_status = torrent.get_status({})
# Email
subject = _('Finished Torrent "%(name)s"') % torrent_status
- message = _(
- 'This email is to inform you that Deluge has finished '
- 'downloading "%(name)s", which includes %(num_files)i files.'
- '\nTo stop receiving these alerts, simply turn off email '
- "notification in Deluge's preferences.\n\n"
- 'Thank you,\nDeluge.',
- ) % torrent_status
+ message = (
+ _(
+ 'This email is to inform you that Deluge has finished '
+ 'downloading "%(name)s", which includes %(num_files)i files.'
+ '\nTo stop receiving these alerts, simply turn off email '
+ "notification in Deluge's preferences.\n\n"
+ 'Thank you,\nDeluge.'
+ )
+ % torrent_status
+ )
return subject, message
# d = defer.maybeDeferred(self.handle_custom_email_notification,
@@ -201,7 +207,7 @@ 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')
diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py
index 86a3daf8c..fba795de6 100644
--- a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py
+++ b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py
@@ -34,12 +34,14 @@ log = logging.getLogger(__name__)
try:
import pygame
+
SOUND_AVAILABLE = True
except ImportError:
SOUND_AVAILABLE = False
try:
import pynotify
+
POPUP_AVAILABLE = True
if deluge.common.windows_check():
POPUP_AVAILABLE = False
@@ -59,36 +61,35 @@ DEFAULT_PREFS = {
'sound_path': '',
'custom_sounds': {},
# Subscriptions
- 'subscriptions': {
- 'popup': [],
- 'blink': [],
- 'sound': [],
- },
+ 'subscriptions': {'popup': [], 'blink': [], 'sound': []},
}
RECIPIENT_FIELD, RECIPIENT_EDIT = list(range(2))
(
- SUB_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
+ 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))
class GtkUiNotifications(CustomNotifications):
-
def __init__(self, plugin_name=None):
CustomNotifications.__init__(self, plugin_name)
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):
@@ -150,19 +151,19 @@ class GtkUiNotifications(CustomNotifications):
return defer.maybeDeferred(self.__blink)
return defer.succeed(
'Will not blink. The returned value from the custom '
- 'handler was: %s' % result,
+ 'handler was: %s' % result
)
def handle_custom_sound_notification(self, result, eventtype):
if isinstance(result, ''.__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,
+ 'custom handler was: %s' % result
)
def __blink(self):
@@ -176,7 +177,9 @@ class GtkUiNotifications(CustomNotifications):
return defer.fail(_('pynotify is not installed'))
if pynotify.init('Deluge'):
- icon = gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap('deluge.svg'), 48, 48)
+ icon = gtk.gdk.pixbuf_new_from_file_at_size(
+ deluge.common.get_pixmap('deluge.svg'), 48, 48
+ )
self.note = pynotify.Notification(title, message)
self.note.set_icon_from_pixbuf(icon)
if not self.note.show():
@@ -227,15 +230,17 @@ class GtkUiNotifications(CustomNotifications):
def _on_torrent_finished_event_got_torrent_status(self, torrent_status):
log.debug(
- 'Handler for TorrentFinishedEvent GTKUI called. '
- 'Got Torrent Status',
+ '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
@@ -246,7 +251,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'))
@@ -259,65 +264,52 @@ 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_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,
- })
+ 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_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,
+ }
+ )
component.get('Preferences').add_page(_('Notifications'), self.prefs)
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
)
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').set_property('sensitive', False)
self.builder.get_object('sounds_page_label').set_property(
- 'sensitive',
- False,
+ '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)
@@ -325,12 +317,10 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
GtkUiNotifications.disable(self)
component.get('Preferences').remove_page(_('Notifications'))
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 build_recipients_model_populate_treeview(self):
@@ -338,7 +328,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
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)
@@ -346,9 +336,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
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,
+ 'Recipients', renderer, text=RECIPIENT_FIELD, editable=RECIPIENT_EDIT
)
column.set_expand(True)
self.recipients_treeview.append_column(column)
@@ -358,9 +346,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
# Sound customisation treeview/model
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,
- )
+ sounds_selection.connect('changed', self.on_sounds_treeview_selection_changed)
self.sounds_treeview.set_tooltip_column(SND_EVENT_DOC)
self.sounds_model = gtk.ListStore(str, str, str, str)
@@ -395,7 +381,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)
@@ -441,7 +427,9 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.subscriptions_treeview.append_column(column)
self.subscriptions_treeview.set_model(self.subscriptions_model)
- def popuplate_what_needs_handled_events(self, handled_events, email_subscriptions=None):
+ def popuplate_what_needs_handled_events(
+ self, handled_events, email_subscriptions=None
+ ):
if email_subscriptions is None:
email_subscriptions = []
self.populate_subscriptions(handled_events, email_subscriptions)
@@ -458,10 +446,14 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
if snd_path:
self.sounds_model.set(
self.sounds_model.append(),
- SND_EVENT, event_name,
- SND_EVENT_DOC, event_doc,
- SND_NAME, basename(snd_path),
- SND_PATH, snd_path,
+ SND_EVENT,
+ event_name,
+ SND_EVENT_DOC,
+ event_doc,
+ SND_NAME,
+ basename(snd_path),
+ SND_PATH,
+ snd_path,
)
def populate_subscriptions(self, handled_events, email_subscriptions=None):
@@ -469,16 +461,22 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
email_subscriptions = []
subscriptions_dict = self.config['subscriptions']
self.subscriptions_model.clear()
-# self.handled_events = handled_events
+ # self.handled_events = handled_events
for event_name, event_doc in handled_events:
self.subscriptions_model.set(
self.subscriptions_model.append(),
- SUB_EVENT, event_name,
- SUB_EVENT_DOC, event_doc,
- SUB_NOT_EMAIL, event_name in email_subscriptions,
- SUB_NOT_POPUP, event_name in subscriptions_dict['popup'],
- SUB_NOT_BLINK, event_name in subscriptions_dict['blink'],
- SUB_NOT_SOUND, event_name in subscriptions_dict['sound'],
+ SUB_EVENT,
+ event_name,
+ SUB_EVENT_DOC,
+ event_doc,
+ SUB_NOT_EMAIL,
+ event_name in email_subscriptions,
+ SUB_NOT_POPUP,
+ event_name in subscriptions_dict['popup'],
+ SUB_NOT_BLINK,
+ event_name in subscriptions_dict['blink'],
+ SUB_NOT_SOUND,
+ event_name in subscriptions_dict['sound'],
)
def on_apply_prefs(self):
@@ -501,8 +499,7 @@ 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,
+ '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:
@@ -511,18 +508,20 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
continue
custom_sounds[event_name] = filepath
- self.config.config.update({
- 'popup_enabled': self.builder.get_object('popup_enabled').get_active(),
- 'blink_enabled': self.builder.get_object('blink_enabled').get_active(),
- 'sound_enabled': self.builder.get_object('sound_enabled').get_active(),
- 'sound_path': new_sound_file,
- 'subscriptions': {
- 'popup': current_popup_subscriptions,
- 'blink': current_blink_subscriptions,
- 'sound': current_sound_subscriptions,
- },
- 'custom_sounds': custom_sounds,
- })
+ self.config.config.update(
+ {
+ 'popup_enabled': self.builder.get_object('popup_enabled').get_active(),
+ 'blink_enabled': self.builder.get_object('blink_enabled').get_active(),
+ 'sound_enabled': self.builder.get_object('sound_enabled').get_active(),
+ 'sound_path': new_sound_file,
+ 'subscriptions': {
+ 'popup': current_popup_subscriptions,
+ 'blink': current_blink_subscriptions,
+ 'sound': current_sound_subscriptions,
+ },
+ 'custom_sounds': custom_sounds,
+ }
+ )
self.config.save()
core_config = {
@@ -534,8 +533,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
'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'
+ dest[0] for dest in self.recipients_model if dest[0] != 'USER@HOST'
],
'subscriptions': {'email': current_email_subscriptions},
}
@@ -558,20 +556,20 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
for recipient in core_config['smtp_recipients']:
self.recipients_model.set(
self.recipients_model.append(),
- RECIPIENT_FIELD, recipient,
- RECIPIENT_EDIT, False,
+ RECIPIENT_FIELD,
+ recipient,
+ RECIPIENT_EDIT,
+ False,
)
- self.builder.get_object('smtp_enabled').set_active(
- core_config['smtp_enabled'],
- )
+ self.builder.get_object('smtp_enabled').set_active(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']
@@ -588,17 +586,11 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
)
def on_sound_path_update_preview(self, filechooser):
- client.notifications.get_handled_events().addCallback(
- self.populate_sounds,
- )
+ client.notifications.get_handled_events().addCallback(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()
@@ -613,42 +605,40 @@ 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()
if selected_iter:
- self.builder.get_object('sounds_edit_button').set_property('sensitive', True)
+ self.builder.get_object('sounds_edit_button').set_property(
+ 'sensitive', True
+ )
path = model.get(selected_iter, SND_PATH)[0]
log.debug('Sound selection changed: %s', path)
if path != self.config['sound_path']:
- self.builder.get_object('sounds_revert_button').set_property('sensitive', True)
+ self.builder.get_object('sounds_revert_button').set_property(
+ 'sensitive', True
+ )
else:
- self.builder.get_object('sounds_revert_button').set_property('sensitive', False)
+ self.builder.get_object('sounds_revert_button').set_property(
+ 'sensitive', False
+ )
else:
- self.builder.get_object('sounds_edit_button').set_property('sensitive', False)
- self.builder.get_object('sounds_revert_button').set_property('sensitive', False)
+ self.builder.get_object('sounds_edit_button').set_property(
+ 'sensitive', False
+ )
+ self.builder.get_object('sounds_revert_button').set_property(
+ 'sensitive', False
+ )
def on_sounds_revert_button_clicked(self, widget):
log.debug('on_sounds_revert_button_clicked')
@@ -658,8 +648,10 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
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']),
+ SND_PATH,
+ self.config['sound_path'],
+ SND_NAME,
+ basename(self.config['sound_path']),
)
def on_sounds_edit_button_clicked(self, widget):
@@ -686,9 +678,12 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
log.debug(new_filename)
model.set(
selected_iter,
- SND_PATH, new_filename,
- SND_NAME, basename(new_filename),
+ SND_PATH,
+ new_filename,
+ SND_NAME,
+ basename(new_filename),
)
+
d = defer.maybeDeferred(dialog.run)
d.addCallback(update_model)
@@ -696,57 +691,55 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
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_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(),
+ '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').set_property('sensitive', False)
self.builder.get_object('sounds_page_label').set_property(
- 'sensitive',
- False,
+ 'sensitive', False
)
-# for widget_name in ('sounds_path', 'sounds_page', 'sounds_page_label'):
-# self.builder.get_object(widget_name).set_property('sensitive',
-# widget.get_active())
+ # for widget_name in ('sounds_path', 'sounds_page', 'sounds_page_label'):
+ # self.builder.get_object(widget_name).set_property('sensitive',
+ # widget.get_active())
def _on_email_col_toggled(self, cell, path):
- self.subscriptions_model[path][SUB_NOT_EMAIL] = \
- not self.subscriptions_model[path][SUB_NOT_EMAIL]
+ self.subscriptions_model[path][SUB_NOT_EMAIL] = not self.subscriptions_model[
+ path
+ ][SUB_NOT_EMAIL]
return
def _on_popup_col_toggled(self, cell, path):
- self.subscriptions_model[path][SUB_NOT_POPUP] = \
- not self.subscriptions_model[path][SUB_NOT_POPUP]
+ self.subscriptions_model[path][SUB_NOT_POPUP] = not self.subscriptions_model[
+ path
+ ][SUB_NOT_POPUP]
return
def _on_blink_col_toggled(self, cell, path):
- self.subscriptions_model[path][SUB_NOT_BLINK] = \
- not self.subscriptions_model[path][SUB_NOT_BLINK]
+ self.subscriptions_model[path][SUB_NOT_BLINK] = not self.subscriptions_model[
+ path
+ ][SUB_NOT_BLINK]
return
def _on_sound_col_toggled(self, cell, path):
- self.subscriptions_model[path][SUB_NOT_SOUND] = \
- not self.subscriptions_model[path][SUB_NOT_SOUND]
+ self.subscriptions_model[path][SUB_NOT_SOUND] = not self.subscriptions_model[
+ path
+ ][SUB_NOT_SOUND]
return
diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/test.py b/deluge/plugins/Notifications/deluge/plugins/notifications/test.py
index 642442c5e..2e6f9755b 100644
--- a/deluge/plugins/Notifications/deluge/plugins/notifications/test.py
+++ b/deluge/plugins/Notifications/deluge/plugins/notifications/test.py
@@ -32,10 +32,7 @@ class TestEmailNotifications(component.Component):
self.__imp = imp
self.lc = task.LoopingCall(self.update)
self.n = 1
- self.events = [
- FooEvent(),
- CustomEvent(),
- ]
+ self.events = [FooEvent(), CustomEvent()]
self.events_classes = []
def enable(self):
@@ -44,22 +41,18 @@ class TestEmailNotifications(component.Component):
if self.__imp == 'core':
# component.get('CorePlugin.Notifications').register_custom_email_notification(
component.get('Notifications').register_custom_email_notification(
- event.__class__.__name__,
- self.custom_email_message_provider,
+ event.__class__.__name__, 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,
+ event.__class__.__name__, self.custom_popup_message_provider
)
notifications_component.register_custom_blink_notification(
- event.__class__.__name__,
- self.custom_blink_message_provider,
+ event.__class__.__name__, self.custom_blink_message_provider
)
notifications_component.register_custom_sound_notification(
- event.__class__.__name__,
- self.custom_sound_message_provider,
+ event.__class__.__name__, self.custom_sound_message_provider
)
self.lc.start(60, False)
diff --git a/deluge/plugins/Notifications/setup.py b/deluge/plugins/Notifications/setup.py
index 84893f53c..b24178047 100755
--- a/deluge/plugins/Notifications/setup.py
+++ b/deluge/plugins/Notifications/setup.py
@@ -40,11 +40,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
-
packages=find_packages(exclude=['**/test.py']),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -52,5 +50,6 @@ 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),
)
diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/__init__.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/__init__.py
index 7d3492d2c..6db72b63b 100644
--- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/__init__.py
+++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/__init__.py
@@ -19,6 +19,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -26,6 +27,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -33,5 +35,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py
index c1e9da999..388e4f0f6 100644
--- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py
+++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/core.py
@@ -35,11 +35,7 @@ DEFAULT_PREFS = {
'button_state': [[0] * 7 for dummy in range(24)],
}
-STATES = {
- 0: 'Green',
- 1: 'Yellow',
- 2: 'Red',
-}
+STATES = {0: 'Green', 1: 'Yellow', 2: 'Red'}
CONTROLLED_SETTINGS = [
'max_download_speed',
@@ -54,6 +50,7 @@ class SchedulerEvent(DelugeEvent):
"""
Emitted when a schedule state changes.
"""
+
def __init__(self, colour):
"""
:param colour: str, the current scheduler state
@@ -71,7 +68,9 @@ class Core(CorePluginBase):
DEFAULT_PREFS['low_active_down'] = core_config['max_active_downloading']
DEFAULT_PREFS['low_active_up'] = core_config['max_active_seeding']
- self.config = deluge.configmanager.ConfigManager('scheduler.conf', DEFAULT_PREFS)
+ self.config = deluge.configmanager.ConfigManager(
+ 'scheduler.conf', DEFAULT_PREFS
+ )
self.state = self.get_state()
@@ -84,12 +83,16 @@ class Core(CorePluginBase):
self.timer = reactor.callLater(secs_to_next_hour, self.do_schedule)
# Register for config changes so state isn't overridden
- component.get('EventManager').register_event_handler('ConfigValueChangedEvent', self.on_config_value_changed)
+ component.get('EventManager').register_event_handler(
+ 'ConfigValueChangedEvent', self.on_config_value_changed
+ )
def disable(self):
if self.timer.active():
self.timer.cancel()
- component.get('EventManager').deregister_event_handler('ConfigValueChangedEvent', self.on_config_value_changed)
+ component.get('EventManager').deregister_event_handler(
+ 'ConfigValueChangedEvent', self.on_config_value_changed
+ )
self.__apply_set_functions()
def update(self):
@@ -105,7 +108,9 @@ class Core(CorePluginBase):
"""
core_config = deluge.configmanager.ConfigManager('core.conf')
for setting in CONTROLLED_SETTINGS:
- component.get('PreferencesManager').do_config_set_func(setting, core_config[setting])
+ component.get('PreferencesManager').do_config_set_func(
+ setting, core_config[setting]
+ )
# Resume the session if necessary
component.get('Core').resume_session()
diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py
index 660101f7f..2525a5f9e 100644
--- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py
+++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py
@@ -32,8 +32,10 @@ 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,
+ 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)
@@ -65,7 +67,9 @@ class SchedulerSelectWidget(gtk.DrawingArea):
# redraw the whole thing
def expose(self, widget, event):
context = self.window.cairo_create()
- context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
+ context.rectangle(
+ event.area.x, event.area.y, event.area.width, event.area.height
+ )
context.clip()
width = self.window.get_size()[0]
@@ -76,11 +80,14 @@ class SchedulerSelectWidget(gtk.DrawingArea):
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,
+ 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,
+ 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)
@@ -132,17 +139,25 @@ class SchedulerSelectWidget(gtk.DrawingArea):
self.hover_point = self.get_point(event)
self.hover_label.set_text(
- self.hover_days[self.hover_point[1]] +
- ' ' + str(self.hover_point[0]) +
- ':00 - ' + str(self.hover_point[0]) + ':59',
+ 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]]]
+ points = [
+ [self.hover_point[0], self.start_point[0]],
+ [self.hover_point[1], self.start_point[1]],
+ ]
for x in range(min(points[0]), max(points[0]) + 1):
for y in range(min(points[1]), max(points[1]) + 1):
- self.button_state[x][y] = self.button_state[self.start_point[0]][self.start_point[1]]
+ self.button_state[x][y] = self.button_state[
+ self.start_point[0]
+ ][self.start_point[1]]
self.queue_draw()
@@ -156,8 +171,12 @@ class GtkUI(GtkPluginBase):
def enable(self):
self.create_prefs_page()
- component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
+ component.get('PluginManager').register_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').register_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
self.statusbar = component.get('StatusBar')
self.status_item = self.statusbar.add_item(
image=get_resource('green.png'),
@@ -169,20 +188,29 @@ class GtkUI(GtkPluginBase):
def on_state_deferred(state):
self.state = state
self.on_scheduler_event(state)
+
client.scheduler.get_state().addCallback(on_state_deferred)
client.register_event_handler('SchedulerEvent', self.on_scheduler_event)
def disable(self):
component.get('Preferences').remove_page(_('Scheduler'))
# Reset statusbar dict.
- self.statusbar.config_value_changed_dict['max_download_speed'] = self.statusbar._on_max_download_speed
- self.statusbar.config_value_changed_dict['max_upload_speed'] = self.statusbar._on_max_upload_speed
+ self.statusbar.config_value_changed_dict[
+ 'max_download_speed'
+ ] = self.statusbar._on_max_download_speed
+ self.statusbar.config_value_changed_dict[
+ 'max_upload_speed'
+ ] = self.statusbar._on_max_upload_speed
# Remove statusbar item.
self.statusbar.remove_item(self.status_item)
del self.status_item
- component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
+ component.get('PluginManager').deregister_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').deregister_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
def on_apply_prefs(self):
log.debug('applying prefs for Scheduler')
@@ -221,8 +249,12 @@ class GtkUI(GtkPluginBase):
# Skip error due to Plugin being enabled before statusbar items created on startup.
pass
else:
- self.statusbar.config_value_changed_dict['max_download_speed'] = self.statusbar._on_max_download_speed
- self.statusbar.config_value_changed_dict['max_upload_speed'] = self.statusbar._on_max_upload_speed
+ self.statusbar.config_value_changed_dict[
+ 'max_download_speed'
+ ] = self.statusbar._on_max_download_speed
+ self.statusbar.config_value_changed_dict[
+ 'max_upload_speed'
+ ] = self.statusbar._on_max_upload_speed
def update_config_values(config):
try:
@@ -231,7 +263,10 @@ class GtkUI(GtkPluginBase):
except AttributeError:
# Skip error due to Plugin being enabled before statusbar items created on startup.
pass
- client.core.get_config_values(['max_download_speed', 'max_upload_speed']).addCallback(update_config_values)
+
+ client.core.get_config_values(
+ ['max_download_speed', 'max_upload_speed']
+ ).addCallback(update_config_values)
def on_status_item_clicked(self, widget, event):
component.get('Preferences').show('Scheduler')
diff --git a/deluge/plugins/Scheduler/setup.py b/deluge/plugins/Scheduler/setup.py
index ea9c6bbcf..16fadd067 100644
--- a/deluge/plugins/Scheduler/setup.py
+++ b/deluge/plugins/Scheduler/setup.py
@@ -32,11 +32,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -44,5 +42,6 @@ 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),
)
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/__init__.py b/deluge/plugins/Stats/deluge/plugins/stats/__init__.py
index 77c85128e..a40379b9a 100644
--- a/deluge/plugins/Stats/deluge/plugins/stats/__init__.py
+++ b/deluge/plugins/Stats/deluge/plugins/stats/__init__.py
@@ -19,6 +19,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -26,6 +27,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -33,5 +35,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/core.py b/deluge/plugins/Stats/deluge/plugins/stats/core.py
index a269516a3..635c54db6 100644
--- a/deluge/plugins/Stats/deluge/plugins/stats/core.py
+++ b/deluge/plugins/Stats/deluge/plugins/stats/core.py
@@ -119,13 +119,15 @@ class Core(CorePluginBase):
stats.update(self.core.get_session_status([key]))
except AttributeError:
pass
- stats['num_connections'] = stats['num_peers'] + stats['peer.num_peers_half_open']
+ 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:
@@ -195,7 +197,12 @@ 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
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/graph.py b/deluge/plugins/Stats/deluge/plugins/stats/graph.py
index e87148e70..d0d1e83c6 100644
--- a/deluge/plugins/Stats/deluge/plugins/stats/graph.py
+++ b/deluge/plugins/Stats/deluge/plugins/stats/graph.py
@@ -136,7 +136,9 @@ class Graph(object):
seconds_to_step = math.ceil(start / x_step) * x_step - start
for i in range(0, duration // x_step + 1):
- text = time.strftime('%H:%M', time.localtime(start + seconds_to_step + i * x_step))
+ text = time.strftime(
+ '%H:%M', time.localtime(start + seconds_to_step + i * x_step)
+ )
# + 0.5 to allign x to nearest pixel
x = int(ratio * (seconds_to_step + i * x_step) + left) + 0.5
self.draw_x_text(text, x, bottom)
@@ -171,6 +173,7 @@ class Graph(object):
def space_required(text):
te = self.ctx.text_extents(text)
return math.ceil(te[4] - te[0])
+
y_tick_width = max((space_required(text) for text in y_tick_text))
top = font_extents[2] / 2
@@ -220,7 +223,9 @@ class Graph(object):
else:
interval = interval * 2
- intervals = [i * interval * scale for i in range(1 + int(math.ceil(x / interval)))]
+ intervals = [
+ i * interval * scale for i in range(1 + int(math.ceil(x / interval)))
+ ]
return intervals
def draw_left_axis(self, bounds, y_ticks, y_tick_text):
@@ -247,7 +252,9 @@ class Graph(object):
for stat, info in stats.items():
if len(info['values']) > 0:
self.draw_value_poly(info['values'], info['color'], max_value, bounds)
- self.draw_value_poly(info['values'], info['fill_color'], max_value, bounds, info['fill'])
+ self.draw_value_poly(
+ info['values'], info['fill_color'], max_value, bounds, info['fill']
+ )
def draw_legend(self):
pass
@@ -271,10 +278,7 @@ class Graph(object):
self.ctx.line_to(x, int(bottom - value * ratio))
x -= step
- self.ctx.line_to(
- int(right - (len(values) - 1) * step),
- bottom,
- )
+ self.ctx.line_to(int(right - (len(values) - 1) * step), bottom)
self.ctx.close_path()
def draw_value_poly(self, values, color, max_value, bounds, fill=False):
@@ -305,7 +309,9 @@ class Graph(object):
ascent = fe[0]
x_bearing = te[0]
width = te[4]
- self.ctx.move_to(int(x - width - x_bearing - 2), int(y + (ascent - descent) / 2))
+ self.ctx.move_to(
+ int(x - width - x_bearing - 2), int(y + (ascent - descent) / 2)
+ )
self.ctx.set_source_rgba(*self.black)
self.ctx.show_text(text)
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py b/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py
index f1d664f31..f7083773e 100644
--- a/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py
+++ b/deluge/plugins/Stats/deluge/plugins/stats/gtkui.py
@@ -43,9 +43,7 @@ DEFAULT_CONF = {
'dht_torrents': str(gtk.gdk.Color('green')),
'num_connections': str(gtk.gdk.Color('darkred')),
},
- 'seeds_graph': {
- 'num_peers': str(gtk.gdk.Color('blue')),
- },
+ 'seeds_graph': {'num_peers': str(gtk.gdk.Color('blue'))},
},
}
@@ -126,7 +124,9 @@ class GraphsTab(Tab):
def graph_expose(self, widget, event):
context = self.graph_widget.window.cairo_create()
# set a clip region
- context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
+ context.rectangle(
+ event.area.x, event.area.y, event.area.width, event.area.height
+ )
context.clip()
self.graph.draw_to_context(
context,
@@ -143,6 +143,7 @@ class GraphsTab(Tab):
def _update_complete(result):
self.graph_widget.queue_draw()
return result
+
d1.addCallback(_update_complete)
return d1
@@ -158,16 +159,17 @@ class GraphsTab(Tab):
self.graph = Graph()
colors = self.colors['bandwidth_graph']
self.graph.add_stat(
- 'download_rate', label='Download Rate',
+ 'download_rate',
+ label='Download Rate',
color=gtk_to_graph_color(colors['download_rate']),
)
self.graph.add_stat(
- 'upload_rate', label='Upload Rate',
+ '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,
+ formatter=fspeed_shortform, min=10240, formatter_scale=size_formatter_scale
)
def select_connections_graph(self):
@@ -177,9 +179,13 @@ class GraphsTab(Tab):
self.graph = g
colors = self.colors['connections_graph']
g.add_stat('dht_nodes', color=gtk_to_graph_color(colors['dht_nodes']))
- g.add_stat('dht_cache_nodes', color=gtk_to_graph_color(colors['dht_cache_nodes']))
+ g.add_stat(
+ 'dht_cache_nodes', color=gtk_to_graph_color(colors['dht_cache_nodes'])
+ )
g.add_stat('dht_torrents', color=gtk_to_graph_color(colors['dht_torrents']))
- g.add_stat('num_connections', color=gtk_to_graph_color(colors['num_connections']))
+ g.add_stat(
+ 'num_connections', color=gtk_to_graph_color(colors['num_connections'])
+ )
g.set_left_axis(formatter=int_str, min=10)
def select_seeds_graph(self):
@@ -194,9 +200,7 @@ class GraphsTab(Tab):
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.notebook, None, self.notebook.get_current_page() # This is unused
)
def _on_intervals_changed(self, intervals):
@@ -233,17 +237,24 @@ class GraphsTab(Tab):
class GtkUI(GtkPluginBase):
-
def enable(self):
log.debug('Stats plugin enable called')
- self.config = deluge.configmanager.ConfigManager('stats.gtkui.conf', DEFAULT_CONF)
+ self.config = deluge.configmanager.ConfigManager(
+ 'stats.gtkui.conf', DEFAULT_CONF
+ )
self.builder = gtk.Builder()
self.builder.add_from_file(get_resource('config.ui'))
- component.get('Preferences').add_page('Stats', self.builder.get_object('prefs_box'))
- component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
+ component.get('Preferences').add_page(
+ 'Stats', self.builder.get_object('prefs_box')
+ )
+ component.get('PluginManager').register_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').register_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
self.on_show_prefs()
self.graphs_tab = GraphsTab(self.config['colors'])
@@ -252,8 +263,12 @@ class GtkUI(GtkPluginBase):
def disable(self):
component.get('Preferences').remove_page('Stats')
- component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
+ component.get('PluginManager').deregister_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').deregister_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
self.torrent_details.remove_tab(self.graphs_tab.get_name())
def on_apply_prefs(self):
diff --git a/deluge/plugins/Stats/deluge/plugins/stats/tests/test_stats.py b/deluge/plugins/Stats/deluge/plugins/stats/tests/test_stats.py
index ca5f2bdf7..60dd7768f 100644
--- a/deluge/plugins/Stats/deluge/plugins/stats/tests/test_stats.py
+++ b/deluge/plugins/Stats/deluge/plugins/stats/tests/test_stats.py
@@ -27,7 +27,6 @@ def print_totals(totals):
class StatsTestCase(BaseTestCase):
-
def set_up(self):
defer.setDebugging(True)
tests_common.set_tmp_config_dir()
diff --git a/deluge/plugins/Stats/setup.py b/deluge/plugins/Stats/setup.py
index 593f68271..a3eeb9769 100644
--- a/deluge/plugins/Stats/setup.py
+++ b/deluge/plugins/Stats/setup.py
@@ -36,11 +36,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -48,5 +46,6 @@ 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),
)
diff --git a/deluge/plugins/Toggle/deluge/plugins/toggle/__init__.py b/deluge/plugins/Toggle/deluge/plugins/toggle/__init__.py
index b83206a77..e63e4aa4c 100644
--- a/deluge/plugins/Toggle/deluge/plugins/toggle/__init__.py
+++ b/deluge/plugins/Toggle/deluge/plugins/toggle/__init__.py
@@ -20,6 +20,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -27,6 +28,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -34,5 +36,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/Toggle/deluge/plugins/toggle/core.py b/deluge/plugins/Toggle/deluge/plugins/toggle/core.py
index eb734275f..dad52ce61 100644
--- a/deluge/plugins/Toggle/deluge/plugins/toggle/core.py
+++ b/deluge/plugins/Toggle/deluge/plugins/toggle/core.py
@@ -22,8 +22,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
-DEFAULT_PREFS = {
-}
+DEFAULT_PREFS = {}
class Core(CorePluginBase):
diff --git a/deluge/plugins/Toggle/deluge/plugins/toggle/gtkui.py b/deluge/plugins/Toggle/deluge/plugins/toggle/gtkui.py
index 7fcce70f0..1be3faef7 100644
--- a/deluge/plugins/Toggle/deluge/plugins/toggle/gtkui.py
+++ b/deluge/plugins/Toggle/deluge/plugins/toggle/gtkui.py
@@ -29,8 +29,10 @@ class GtkUI(GtkPluginBase):
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._on_button_clicked,
+ label='Pause Session',
+ stock='gtk-media-pause',
+ tooltip='Pause the session',
)
def disable(self):
@@ -47,6 +49,7 @@ class GtkUI(GtkPluginBase):
self.button.set_label('Pause Session')
self.button.set_tooltip_text('Pause the session')
self.button.set_stock_id('gtk-media-pause')
+
self.core.get_status().addCallback(_on_get_status)
def _on_button_clicked(self, widget):
diff --git a/deluge/plugins/Toggle/setup.py b/deluge/plugins/Toggle/setup.py
index d3a754bdc..3dcf83f4d 100644
--- a/deluge/plugins/Toggle/setup.py
+++ b/deluge/plugins/Toggle/setup.py
@@ -33,11 +33,9 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%s = deluge.plugins.%s:CorePlugin
@@ -45,5 +43,6 @@ 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),
)
diff --git a/deluge/plugins/WebUi/deluge/plugins/webui/__init__.py b/deluge/plugins/WebUi/deluge/plugins/webui/__init__.py
index 2e53a6b59..a3d29805a 100644
--- a/deluge/plugins/WebUi/deluge/plugins/webui/__init__.py
+++ b/deluge/plugins/WebUi/deluge/plugins/webui/__init__.py
@@ -19,6 +19,7 @@ from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from .core import Core as _pluginCls
+
self._plugin_cls = _pluginCls
super(CorePlugin, self).__init__(plugin_name)
@@ -26,6 +27,7 @@ class CorePlugin(PluginInitBase):
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from .gtkui import GtkUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(GtkUIPlugin, self).__init__(plugin_name)
@@ -33,5 +35,6 @@ class GtkUIPlugin(PluginInitBase):
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from webui import WebUI as _pluginCls
+
self._plugin_cls = _pluginCls
super(WebUIPlugin, self).__init__(plugin_name)
diff --git a/deluge/plugins/WebUi/deluge/plugins/webui/core.py b/deluge/plugins/WebUi/deluge/plugins/webui/core.py
index 72923a6f0..cc3330fc0 100644
--- a/deluge/plugins/WebUi/deluge/plugins/webui/core.py
+++ b/deluge/plugins/WebUi/deluge/plugins/webui/core.py
@@ -30,11 +30,7 @@ except ImportError:
log = logging.getLogger(__name__)
-DEFAULT_PREFS = {
- 'enabled': False,
- 'ssl': False,
- 'port': 8112,
-}
+DEFAULT_PREFS = {'enabled': False, 'ssl': False, 'port': 8112}
class Core(CorePluginBase):
diff --git a/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py b/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py
index 992c9b038..f72769868 100644
--- a/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py
+++ b/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py
@@ -31,16 +31,26 @@ class GtkUI(GtkPluginBase):
self.builder = gtk.Builder()
self.builder.add_from_file(get_resource('config.ui'))
- component.get('Preferences').add_page(_('WebUi'), self.builder.get_object('prefs_box'))
- component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
+ component.get('Preferences').add_page(
+ _('WebUi'), self.builder.get_object('prefs_box')
+ )
+ component.get('PluginManager').register_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').register_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
client.webui.get_config().addCallback(self.cb_get_config)
client.webui.got_deluge_web().addCallback(self.cb_chk_deluge_web)
def disable(self):
component.get('Preferences').remove_page(_('WebUi'))
- component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
- component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
+ component.get('PluginManager').deregister_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').deregister_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
def on_apply_prefs(self):
if not self.have_web:
@@ -71,14 +81,18 @@ class GtkUI(GtkPluginBase):
vbox = self.builder.get_object('prefs_box')
hbox = gtk.HBox()
- icon = gtk.image_new_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_SMALL_TOOLBAR)
+ icon = gtk.image_new_from_stock(
+ gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_SMALL_TOOLBAR
+ )
icon.set_padding(5, 5)
hbox.pack_start(icon, False, False)
- label = gtk.Label(_(
- 'The Deluge web interface is not installed, '
- 'please install the\ninterface and try again',
- ))
+ label = gtk.Label(
+ _(
+ 'The Deluge web interface is not installed, '
+ 'please install the\ninterface and try again'
+ )
+ )
label.set_alignment(0, 0.5)
label.set_padding(5, 5)
hbox.pack_start(label)
diff --git a/deluge/plugins/WebUi/deluge/plugins/webui/tests/test_plugin_webui.py b/deluge/plugins/WebUi/deluge/plugins/webui/tests/test_plugin_webui.py
index 8f70a19b3..56e1cc023 100644
--- a/deluge/plugins/WebUi/deluge/plugins/webui/tests/test_plugin_webui.py
+++ b/deluge/plugins/WebUi/deluge/plugins/webui/tests/test_plugin_webui.py
@@ -21,7 +21,6 @@ common.disable_new_release_check()
class WebUIPluginTestCase(BaseTestCase):
-
def set_up(self):
common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
@@ -29,10 +28,10 @@ class WebUIPluginTestCase(BaseTestCase):
return component.start()
def tear_down(self):
-
def on_shutdown(result):
del self.rpcserver
del self.core
+
return component.shutdown().addCallback(on_shutdown)
def test_enable_webui(self):
diff --git a/deluge/plugins/WebUi/setup.py b/deluge/plugins/WebUi/setup.py
index 7bc61259e..646467882 100644
--- a/deluge/plugins/WebUi/setup.py
+++ b/deluge/plugins/WebUi/setup.py
@@ -32,15 +32,14 @@ setup(
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
-
packages=find_packages(),
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
-
entry_points="""
[deluge.plugin.core]
%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),
)
diff --git a/deluge/plugins/pluginbase.py b/deluge/plugins/pluginbase.py
index 5bc3e1c59..4ae268d68 100644
--- a/deluge/plugins/pluginbase.py
+++ b/deluge/plugins/pluginbase.py
@@ -31,7 +31,6 @@ class PluginBase(component.Component):
class CorePluginBase(PluginBase):
-
def __init__(self, plugin_name):
super(CorePluginBase, self).__init__('CorePlugin.' + plugin_name)
# Register RPC methods
@@ -49,7 +48,6 @@ class CorePluginBase(PluginBase):
class GtkPluginBase(PluginBase):
-
def __init__(self, plugin_name):
super(GtkPluginBase, self).__init__('GtkPlugin.' + plugin_name)
log.debug('GtkPlugin initialized..')
diff --git a/deluge/rencode.py b/deluge/rencode.py
index 7f5378dee..2237dde3a 100644
--- a/deluge/rencode.py
+++ b/deluge/rencode.py
@@ -78,10 +78,14 @@ if py3:
def int2byte(c):
return bytes([c])
+
+
else:
+
def int2byte(c):
return chr(c)
+
# Default number of bits for serialized floats, either 32 or 64 (also a parameter for dumps()).
DEFAULT_FLOAT_BITS = 32
@@ -137,44 +141,44 @@ def decode_int(x, f):
n = int(x[f:newf])
except (OverflowError, ValueError):
n = long(x[f:newf])
- if x[f:f + 1] == '-':
- if x[f + 1:f + 2] == '0':
+ if x[f : f + 1] == '-':
+ if x[f + 1 : f + 2] == '0':
raise ValueError
- elif x[f:f + 1] == '0' and newf != f + 1:
+ elif x[f : f + 1] == '0' and newf != f + 1:
raise ValueError
return (n, newf + 1)
def decode_intb(x, f):
f += 1
- return (struct.unpack('!b', x[f:f + 1])[0], f + 1)
+ return (struct.unpack('!b', x[f : f + 1])[0], f + 1)
def decode_inth(x, f):
f += 1
- return (struct.unpack('!h', x[f:f + 2])[0], f + 2)
+ return (struct.unpack('!h', x[f : f + 2])[0], f + 2)
def decode_intl(x, f):
f += 1
- return (struct.unpack('!l', x[f:f + 4])[0], f + 4)
+ return (struct.unpack('!l', x[f : f + 4])[0], f + 4)
def decode_intq(x, f):
f += 1
- return (struct.unpack('!q', x[f:f + 8])[0], f + 8)
+ return (struct.unpack('!q', x[f : f + 8])[0], f + 8)
def decode_float32(x, f):
f += 1
- n = struct.unpack('!f', x[f:f + 4])[0]
+ n = struct.unpack('!f', x[f : f + 4])[0]
return (n, f + 4)
def decode_float64(x, f):
f += 1
- n = struct.unpack('!d', x[f:f + 8])[0]
+ n = struct.unpack('!d', x[f : f + 8])[0]
return (n, f + 8)
@@ -187,7 +191,7 @@ def decode_string(x, f):
if x[f] == '0' and colon != f + 1:
raise ValueError
colon += 1
- s = x[colon:colon + n]
+ s = x[colon : colon + n]
if _decode_utf8:
s = s.decode('utf8')
return (s, colon + n)
@@ -195,17 +199,17 @@ def decode_string(x, f):
def decode_list(x, f):
r, f = [], f + 1
- while x[f:f + 1] != CHR_TERM:
- v, f = decode_func[x[f:f + 1]](x, f)
+ while x[f : f + 1] != CHR_TERM:
+ v, f = decode_func[x[f : f + 1]](x, f)
r.append(v)
return (tuple(r), f + 1)
def decode_dict(x, f):
r, f = {}, f + 1
- while x[f:f + 1] != CHR_TERM:
- k, f = decode_func[x[f:f + 1]](x, f)
- r[k], f = decode_func[x[f:f + 1]](x, f)
+ while x[f : f + 1] != CHR_TERM:
+ 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)
@@ -249,11 +253,13 @@ decode_func[CHR_NONE] = decode_none
def make_fixed_length_string_decoders():
def make_decoder(slen):
def f(x, f):
- s = x[f + 1:f + 1 + slen]
+ s = x[f + 1 : f + 1 + slen]
if _decode_utf8:
s = s.decode('utf8')
return (s, f + 1 + slen)
+
return f
+
for i in range(STR_FIXED_COUNT):
decode_func[int2byte(STR_FIXED_START + i)] = make_decoder(i)
@@ -266,10 +272,12 @@ def make_fixed_length_list_decoders():
def f(x, f):
r, f = [], f + 1
for _ in range(slen):
- v, f = decode_func[x[f:f + 1]](x, f)
+ v, f = decode_func[x[f : f + 1]](x, f)
r.append(v)
return (tuple(r), f)
+
return f
+
for i in range(LIST_FIXED_COUNT):
decode_func[int2byte(LIST_FIXED_START + i)] = make_decoder(i)
@@ -281,7 +289,9 @@ def make_fixed_length_int_decoders():
def make_decoder(j):
def f(x, f):
return (j, f + 1)
+
return f
+
for i in range(INT_POS_FIXED_COUNT):
decode_func[int2byte(INT_POS_FIXED_START + i)] = make_decoder(i)
for i in range(INT_NEG_FIXED_COUNT):
@@ -296,10 +306,12 @@ def make_fixed_length_dict_decoders():
def f(x, f):
r, f = {}, f + 1
for _ in range(slen):
- k, f = decode_func[x[f:f + 1]](x, f)
- r[k], f = decode_func[x[f:f + 1]](x, f)
+ k, f = decode_func[x[f : f + 1]](x, f)
+ r[k], f = decode_func[x[f : f + 1]](x, f)
return (r, f)
+
return f
+
for i in range(DICT_FIXED_COUNT):
decode_func[int2byte(DICT_FIXED_START + i)] = make_decoder(i)
@@ -436,17 +448,45 @@ def test():
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,
+ {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})
+ d.update(
+ {b'a': 20, 20: 40, 40: 41, f1: f2, f2: f3, f3: False, False: True, True: False}
+ )
ld = (d, {}, {5: 6}, {7: 7, True: 8}, {9: 10, 22: 39, 49: 50, 44: b''})
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)
+ 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',)
assert loads(dumps(ld)) == ld
@@ -468,6 +508,7 @@ def test():
try:
import psyco
+
psyco.bind(dumps)
psyco.bind(loads)
except ImportError:
diff --git a/deluge/scripts/create_plugin.py b/deluge/scripts/create_plugin.py
index 93b6f8d95..aa58e3425 100644
--- a/deluge/scripts/create_plugin.py
+++ b/deluge/scripts/create_plugin.py
@@ -17,19 +17,35 @@ from datetime import datetime
import deluge.common
parser = ArgumentParser()
-parser.add_argument('-n', '--name', metavar='<plugin name>', required=True, help='Plugin name')
+parser.add_argument(
+ '-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,
+ '-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,
+ '-e',
+ '--author-email',
+ metavar='<author email>',
+ required=True,
help='Author email,for the GPL header',
)
parser.add_argument('-u', '--url', metavar='<URL>', help='Homepage URL')
-parser.add_argument('-c', '--config', metavar='<Config dir>', dest='configdir', help='Location of deluge configuration')
+parser.add_argument(
+ '-c',
+ '--config',
+ metavar='<Config dir>',
+ dest='configdir',
+ help='Location of deluge configuration',
+)
options = parser.parse_args()
diff --git a/deluge/scripts/deluge_remote.py b/deluge/scripts/deluge_remote.py
index c1b5de7b4..bacc4f88d 100644
--- a/deluge/scripts/deluge_remote.py
+++ b/deluge/scripts/deluge_remote.py
@@ -32,33 +32,48 @@ 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',
+ '--port',
+ help='port for deluge backend host (default: 58846)',
+ default='58846',
+ dest='port',
)
parser.add_option(
- '--max_active_limit', dest='max_active_limit',
+ '--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',
+ '--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',
+ '--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',
+ '--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',
+ '--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',
+ '--debug',
+ help='outputs debug information to the console',
+ default=False,
+ action='store_true',
dest='debug',
)
@@ -79,7 +94,10 @@ if options.max_active_limit:
sys.exit(-1)
if options.max_active_downloading:
- if options.max_active_downloading.isdigit() and int(options.max_active_downloading) >= 0:
+ if (
+ options.max_active_downloading.isdigit()
+ and int(options.max_active_downloading) >= 0
+ ):
settings['max_active_downloading'] = int(options.max_active_downloading)
else:
sys.stderr.write('ERROR: Invalid max_active_downloading parameter!\n')
@@ -94,7 +112,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:
@@ -103,7 +122,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:
@@ -114,6 +134,7 @@ if options.max_upload_speed:
if settings:
# create connection to daemon
from deluge.ui.client import sclient as client
+
client.set_core_uri('http://' + options.host + ':' + options.port)
# commit configurations changes
diff --git a/deluge/tests/basetest.py b/deluge/tests/basetest.py
index 19796dca2..11ca18e53 100644
--- a/deluge/tests/basetest.py
+++ b/deluge/tests/basetest.py
@@ -22,13 +22,14 @@ class BaseTestCase(unittest.TestCase):
have finished.
"""
+
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,
+ 'This is probably caused by another test that did not clean up after finishing!: %s'
+ % component._ComponentRegistry.components
)
d = maybeDeferred(self.set_up)
diff --git a/deluge/tests/common.py b/deluge/tests/common.py
index 877b67654..4ca34d400 100644
--- a/deluge/tests/common.py
+++ b/deluge/tests/common.py
@@ -60,7 +60,6 @@ def todo_test(caller):
def add_watchdog(deferred, timeout=0.05, message=None):
-
def callback(value):
if not watchdog.called and not watchdog.cancelled:
watchdog.cancel()
@@ -102,8 +101,9 @@ class ReactorOverride(object):
class ProcessOutputHandler(protocol.ProcessProtocol):
-
- def __init__(self, script, callbacks, logfile=None, print_stdout=True, print_stderr=True):
+ def __init__(
+ self, script, callbacks, logfile=None, print_stdout=True, print_stderr=True
+ ):
"""Executes a script and handle the process' output to stdout and stderr.
Args:
@@ -210,8 +210,14 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
def start_core(
- listen_port=58846, logfile=None, timeout=10, timeout_msg=None,
- custom_script='', print_stdout=True, print_stderr=True, extra_callbacks=None,
+ 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.
@@ -252,7 +258,11 @@ try:
except Exception:
import traceback
sys.stderr.write('Exception raised:\\n %%s' %% traceback.format_exc())
-""" % {'dir': config_directory, 'port': listen_port, 'script': custom_script}
+""" % {
+ 'dir': config_directory,
+ 'port': listen_port,
+ 'script': custom_script,
+ }
callbacks = []
default_core_cb = {'deferred': Deferred(), 'types': 'stdout'}
@@ -263,15 +273,20 @@ except Exception:
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
+ 'expr': 'Could not listen on localhost:%d' % (listen_port),
+ 'type': 'errback', # Error from libtorrent
'value': lambda reader, data, data_all: CannotListenError(
- 'localhost', listen_port,
+ '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': 'Traceback',
+ 'type': 'errback',
+ 'value': lambda reader, data, data_all: DelugeError(
+ 'Traceback found when starting daemon:\n%s' % data
+ ),
},
]
@@ -279,11 +294,15 @@ except Exception:
if extra_callbacks:
callbacks.extend(extra_callbacks)
- process_protocol = start_process(daemon_script, callbacks, logfile, print_stdout, print_stderr)
+ process_protocol = start_process(
+ daemon_script, callbacks, logfile, print_stdout, print_stderr
+ )
return default_core_cb['deferred'], process_protocol
-def start_process(script, callbacks, logfile=None, print_stdout=True, print_stderr=True):
+def start_process(
+ script, callbacks, logfile=None, print_stdout=True, print_stderr=True
+):
"""
Starts an external python process which executes the given script.
@@ -309,13 +328,19 @@ def start_process(script, callbacks, logfile=None, print_stdout=True, print_stde
"""
cwd = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
- process_protocol = ProcessOutputHandler(script.encode('utf8'), callbacks, logfile, print_stdout, print_stderr)
+ process_protocol = ProcessOutputHandler(
+ script.encode('utf8'), callbacks, logfile, print_stdout, print_stderr
+ )
# Add timeouts to deferreds
for c in callbacks:
if 'timeout' in c:
- w = add_watchdog(c['deferred'], timeout=c['timeout'], message=c.get('timeout_msg', None))
+ w = add_watchdog(
+ c['deferred'], timeout=c['timeout'], message=c.get('timeout_msg', None)
+ )
process_protocol.watchdogs.append(w)
- reactor.spawnProcess(process_protocol, sys.executable, args=[sys.executable], path=cwd)
+ reactor.spawnProcess(
+ process_protocol, sys.executable, args=[sys.executable], path=cwd
+ )
return process_protocol
diff --git a/deluge/tests/common_web.py b/deluge/tests/common_web.py
index b9a7ee959..7669fd4da 100644
--- a/deluge/tests/common_web.py
+++ b/deluge/tests/common_web.py
@@ -26,6 +26,7 @@ class WebServerTestBase(BaseTestCase, DaemonBase):
Base class for tests that need a running webapi
"""
+
def set_up(self):
self.host_id = None
deluge.ui.web.server.reactor = ReactorOverride()
@@ -60,16 +61,16 @@ class WebServerMockBase(object):
Class with utility functions for mocking with tests using the webserver
"""
- def mock_authentication_ignore(self, auth):
+ def mock_authentication_ignore(self, auth):
def check_request(request, method=None, level=None):
pass
self.patch(auth, 'check_request', check_request)
def mock_compress_body(self):
-
def compress(contents, request):
return contents
+
# Patch compress to avoid having to decompress output with zlib
self.patch(deluge.ui.web.json_api, 'compress', compress)
diff --git a/deluge/tests/daemon_base.py b/deluge/tests/daemon_base.py
index 9cd286ba3..eda2193e9 100644
--- a/deluge/tests/daemon_base.py
+++ b/deluge/tests/daemon_base.py
@@ -41,8 +41,15 @@ class DaemonBase(object):
@defer.inlineCallbacks
def start_core(
- self, arg, custom_script='', logfile='', print_stdout=True, print_stderr=True, timeout=5,
- port_range=10, extra_callbacks=None,
+ 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()
@@ -59,8 +66,10 @@ 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!',
+ listen_port=self.listen_port,
+ logfile=logfile,
+ timeout=timeout,
+ timeout_msg='Timeout!',
custom_script=custom_script,
print_stdout=print_stdout,
print_stderr=print_stderr,
diff --git a/deluge/tests/test_alertmanager.py b/deluge/tests/test_alertmanager.py
index 0f740394a..f197882cd 100644
--- a/deluge/tests/test_alertmanager.py
+++ b/deluge/tests/test_alertmanager.py
@@ -14,7 +14,6 @@ from .basetest import BaseTestCase
class AlertManagerTestCase(BaseTestCase):
-
def set_up(self):
self.core = Core()
self.core.config.config['lsd'] = False
diff --git a/deluge/tests/test_authmanager.py b/deluge/tests/test_authmanager.py
index d714a5a82..91e122f73 100644
--- a/deluge/tests/test_authmanager.py
+++ b/deluge/tests/test_authmanager.py
@@ -24,7 +24,4 @@ class AuthManagerTestCase(BaseTestCase):
return component.shutdown()
def test_authorize(self):
- self.assertEqual(
- self.auth.authorize(*get_localhost_auth()),
- AUTH_LEVEL_ADMIN,
- )
+ self.assertEqual(self.auth.authorize(*get_localhost_auth()), AUTH_LEVEL_ADMIN)
diff --git a/deluge/tests/test_bencode.py b/deluge/tests/test_bencode.py
index 760a691af..bdad16fa4 100644
--- a/deluge/tests/test_bencode.py
+++ b/deluge/tests/test_bencode.py
@@ -14,7 +14,6 @@ from . import common
class BencodeTestCase(unittest.TestCase):
-
def test_bencode_unicode_metainfo(self):
filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file:
diff --git a/deluge/tests/test_client.py b/deluge/tests/test_client.py
index 9a237f261..c89ad5309 100644
--- a/deluge/tests/test_client.py
+++ b/deluge/tests/test_client.py
@@ -35,9 +35,12 @@ class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
class NoVersionSendingClient(Client):
-
def connect(
- self, host='127.0.0.1', port=58846, username='', password='',
+ self,
+ host='127.0.0.1',
+ port=58846,
+ username='',
+ password='',
skip_authentication=False,
):
self._daemon_proxy = NoVersionSendingDaemonSSLProxy()
@@ -104,7 +107,9 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_localclient(self):
username, password = get_localhost_auth()
- d = client.connect('localhost', self.listen_port, username=username, password=password)
+ d = client.connect(
+ 'localhost', self.listen_port, username=username, password=password
+ )
def on_connect(result):
self.assertEqual(client.get_auth_level(), AUTH_LEVEL_ADMIN)
@@ -116,13 +121,12 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_bad_password(self):
username, password = get_localhost_auth()
- d = client.connect('localhost', self.listen_port, username=username, password=password + '1')
+ d = client.connect(
+ 'localhost', self.listen_port, username=username, password=password + '1'
+ )
def on_failure(failure):
- self.assertEqual(
- failure.trap(error.BadLoginError),
- error.BadLoginError,
- )
+ self.assertEqual(failure.trap(error.BadLoginError), error.BadLoginError)
self.assertEqual(failure.value.message, 'Password does not match')
self.addCleanup(client.disconnect)
@@ -134,10 +138,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
d = client.connect('localhost', self.listen_port, username='invalid-user')
def on_failure(failure):
- self.assertEqual(
- failure.trap(error.BadLoginError),
- error.BadLoginError,
- )
+ self.assertEqual(failure.trap(error.BadLoginError), error.BadLoginError)
self.assertEqual(failure.value.message, 'Username does not exist')
self.addCleanup(client.disconnect)
@@ -150,8 +151,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def on_failure(failure):
self.assertEqual(
- failure.trap(error.AuthenticationRequired),
- error.AuthenticationRequired,
+ failure.trap(error.AuthenticationRequired), error.AuthenticationRequired
)
self.assertEqual(failure.value.username, username)
self.addCleanup(client.disconnect)
@@ -162,10 +162,14 @@ class ClientTestCase(BaseTestCase, DaemonBase):
@defer.inlineCallbacks
def test_connect_with_password(self):
username, password = get_localhost_auth()
- yield client.connect('localhost', self.listen_port, username=username, password=password)
+ yield client.connect(
+ 'localhost', self.listen_port, username=username, password=password
+ )
yield client.core.create_account('testuser', 'testpw', 'DEFAULT')
yield client.disconnect()
- ret = yield client.connect('localhost', self.listen_port, username='testuser', password='testpw')
+ ret = yield client.connect(
+ 'localhost', self.listen_port, username='testuser', password='testpw'
+ )
self.assertEqual(ret, AUTH_LEVEL_NORMAL)
yield
@@ -175,8 +179,11 @@ class ClientTestCase(BaseTestCase, DaemonBase):
d = client.core.invalid_method()
def on_failure(failure):
- self.assertEqual(failure.trap(error.WrappedException), error.WrappedException)
+ self.assertEqual(
+ failure.trap(error.WrappedException), error.WrappedException
+ )
self.addCleanup(client.disconnect)
+
d.addCallbacks(self.fail, on_failure)
yield d
@@ -184,13 +191,12 @@ 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,
+ failure.trap(error.IncompatibleClient), error.IncompatibleClient
)
self.addCleanup(no_version_sending_client.disconnect)
diff --git a/deluge/tests/test_common.py b/deluge/tests/test_common.py
index 0a35ce6af..9b48ae220 100644
--- a/deluge/tests/test_common.py
+++ b/deluge/tests/test_common.py
@@ -12,8 +12,24 @@ import tarfile
from twisted.trial import unittest
-from deluge.common import (VersionSplit, archive_files, fdate, fpcnt, fpeer, fsize, fspeed, ftime, get_path_size,
- is_infohash, is_ip, is_ipv4, is_ipv6, is_magnet, is_url, windows_check)
+from deluge.common import (
+ VersionSplit,
+ archive_files,
+ fdate,
+ fpcnt,
+ fpeer,
+ fsize,
+ fspeed,
+ ftime,
+ get_path_size,
+ is_infohash,
+ is_ip,
+ is_ipv4,
+ is_ipv6,
+ is_magnet,
+ is_url,
+ windows_check,
+)
from deluge.ui.translations_util import setup_translations
from .common import get_test_data_file, set_tmp_config_dir
@@ -73,7 +89,9 @@ class CommonTestCase(unittest.TestCase):
self.assertFalse(is_url('file://test.torrent'))
def test_is_magnet(self):
- self.assertTrue(is_magnet('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN'))
+ self.assertTrue(
+ is_magnet('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN')
+ )
self.assertFalse(is_magnet(None))
def test_is_infohash(self):
@@ -121,23 +139,26 @@ 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),
+ ('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)
- self.assertEqual(parsed, byte_size, 'Mismatch when converting: %s' % human_size)
+ self.assertEqual(
+ parsed, byte_size, 'Mismatch when converting: %s' % human_size
+ )
def test_archive_files(self):
arc_filelist = [
@@ -149,4 +170,6 @@ class CommonTestCase(unittest.TestCase):
with tarfile.open(arc_filepath, 'r') as tar:
for tar_info in tar:
self.assertTrue(tar_info.isfile())
- self.assertTrue(tar_info.name in [os.path.basename(arcf) for arcf in arc_filelist])
+ self.assertTrue(
+ tar_info.name in [os.path.basename(arcf) for arcf in arc_filelist]
+ )
diff --git a/deluge/tests/test_component.py b/deluge/tests/test_component.py
index 06639b0aa..26f24ad00 100644
--- a/deluge/tests/test_component.py
+++ b/deluge/tests/test_component.py
@@ -16,7 +16,6 @@ from .basetest import BaseTestCase
class ComponentTester(component.Component):
-
def __init__(self, name, depend=None):
component.Component.__init__(self, name, depend=depend)
self.start_count = 0
@@ -30,20 +29,21 @@ class ComponentTester(component.Component):
class ComponentTesterDelayStart(ComponentTester):
-
def start(self):
def do_sleep():
import time
+
time.sleep(1)
+
d = threads.deferToThread(do_sleep)
def on_done(result):
self.start_count += 1
+
return d.addCallback(on_done)
class ComponentTesterUpdate(component.Component):
-
def __init__(self, name):
component.Component.__init__(self, name)
self.counter = 0
@@ -58,7 +58,6 @@ class ComponentTesterUpdate(component.Component):
class ComponentTesterShutdown(component.Component):
-
def __init__(self, name):
component.Component.__init__(self, name)
self.shutdowned = False
@@ -72,7 +71,6 @@ class ComponentTesterShutdown(component.Component):
class ComponentTestClass(BaseTestCase):
-
def tear_down(self):
return component.shutdown()
@@ -98,7 +96,9 @@ class ComponentTestClass(BaseTestCase):
self.assertEqual(c2._component_state, 'Started')
self.assertEqual(c1.start_count, 1)
self.assertEqual(c2.start_count, 1)
- return component.stop(['test_start_depends_c1']).addCallback(on_stop, c1, c2)
+ return component.stop(['test_start_depends_c1']).addCallback(
+ on_stop, c1, c2
+ )
c1 = ComponentTester('test_start_depends_c1')
c2 = ComponentTester('test_start_depends_c2', depend=['test_start_depends_c1'])
@@ -110,7 +110,9 @@ class ComponentTestClass(BaseTestCase):
def start_with_depends(self):
c1 = ComponentTesterDelayStart('test_start_all_c1')
c2 = ComponentTester('test_start_all_c2', depend=['test_start_all_c4'])
- c3 = ComponentTesterDelayStart('test_start_all_c3', depend=['test_start_all_c5', 'test_start_all_c1'])
+ c3 = ComponentTesterDelayStart(
+ 'test_start_all_c3', depend=['test_start_all_c5', 'test_start_all_c1']
+ )
c4 = ComponentTester('test_start_all_c4', depend=['test_start_all_c3'])
c5 = ComponentTester('test_start_all_c5')
@@ -214,8 +216,12 @@ class ComponentTestClass(BaseTestCase):
try:
result = self.failureResultOf(test_comp._component_start())
except AttributeError:
- raise SkipTest('This test requires trial failureResultOf() in Twisted version >= 13')
- self.assertEqual(result.check(component.ComponentException), component.ComponentException)
+ raise SkipTest(
+ 'This test requires trial failureResultOf() in Twisted version >= 13'
+ )
+ self.assertEqual(
+ result.check(component.ComponentException), component.ComponentException
+ )
@defer.inlineCallbacks
def test_start_paused_error(self):
@@ -231,14 +237,17 @@ class ComponentTestClass(BaseTestCase):
result = yield component.start()
self.assertEqual(
[(result[0][0], result[0][1].value)],
- [(
- defer.FAILURE,
- component.ComponentException(
- 'Trying to start component "%s" but it is '
- 'not in a stopped state. Current state: %s' %
- ('test_pause_c1', 'Paused'), '',
- ),
- )],
+ [
+ (
+ defer.FAILURE,
+ component.ComponentException(
+ 'Trying to start component "%s" but it is '
+ 'not in a stopped state. Current state: %s'
+ % ('test_pause_c1', 'Paused'),
+ '',
+ ),
+ )
+ ],
)
def test_shutdown(self):
diff --git a/deluge/tests/test_config.py b/deluge/tests/test_config.py
index 091290abc..270cc5a5b 100644
--- a/deluge/tests/test_config.py
+++ b/deluge/tests/test_config.py
@@ -19,7 +19,13 @@ from deluge.config import Config
from .common import set_tmp_config_dir
-DEFAULTS = {'string': 'foobar', 'int': 1, 'float': 0.435, 'bool': True, 'unicode': 'foobar'}
+DEFAULTS = {
+ 'string': 'foobar',
+ 'int': 1,
+ 'float': 0.435,
+ 'bool': True,
+ 'unicode': 'foobar',
+}
class ConfigTestCase(unittest.TestCase):
@@ -92,6 +98,7 @@ class ConfigTestCase(unittest.TestCase):
# Test opening a previous 1.2 config file of just a json object
import json
+
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
json.dump(DEFAULTS, getwriter('utf8')(_file), **JSON_FORMAT)
diff --git a/deluge/tests/test_core.py b/deluge/tests/test_core.py
index be2386d48..62be33e9e 100644
--- a/deluge/tests/test_core.py
+++ b/deluge/tests/test_core.py
@@ -35,22 +35,24 @@ common.disable_new_release_check()
class CookieResource(Resource):
-
def render(self, request):
if request.getCookie(b'password') != b'deluge':
request.setResponseCode(FORBIDDEN)
return
request.setHeader(b'Content-Type', b'application/x-bittorrent')
- with open(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent'), 'rb') as _file:
+ with open(
+ common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent'), 'rb'
+ ) as _file:
data = _file.read()
return data
class PartialDownload(Resource):
-
def render(self, request):
- with open(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent'), 'rb') as _file:
+ with open(
+ common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent'), 'rb'
+ ) as _file:
data = _file.read()
request.setHeader(b'Content-Type', len(data))
request.setHeader(b'Content-Type', b'application/x-bittorrent')
@@ -60,7 +62,6 @@ class PartialDownload(Resource):
class RedirectResource(Resource):
-
def render(self, request):
request.redirect(b'/ubuntu-9.04-desktop-i386.iso.torrent')
return b''
@@ -82,7 +83,6 @@ class TopLevelResource(Resource):
class CoreTestCase(BaseTestCase):
-
def set_up(self):
common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
@@ -109,7 +109,6 @@ class CoreTestCase(BaseTestCase):
return result
def tear_down(self):
-
def on_shutdown(result):
del self.rpcserver
del self.core
@@ -120,11 +119,7 @@ class CoreTestCase(BaseTestCase):
def add_torrent(self, filename, paused=False):
if not paused:
# Patch libtorrent flags starting torrents paused
- self.patch(
- deluge.core.torrentmanager,
- 'LT_DEFAULT_ADD_TORRENT_FLAGS',
- 592,
- )
+ self.patch(deluge.core.torrentmanager, 'LT_DEFAULT_ADD_TORRENT_FLAGS', 592)
options = {'add_paused': paused, 'auto_managed': False}
filepath = common.get_test_data_file(filename)
with open(filepath, 'rb') as _file:
@@ -169,6 +164,7 @@ class CoreTestCase(BaseTestCase):
# Get the info hash from the test.torrent
from deluge.bencode import bdecode, bencode
+
with open(filename, 'rb') as _file:
info_hash = sha(bencode(bdecode(_file.read())[b'info'])).hexdigest()
self.assertEqual(torrent_id, info_hash)
@@ -176,11 +172,16 @@ class CoreTestCase(BaseTestCase):
def test_add_torrent_file_invalid_filedump(self):
options = {}
filename = common.get_test_data_file('test.torrent')
- self.assertRaises(AddTorrentError, self.core.add_torrent_file, filename, False, options)
+ self.assertRaises(
+ AddTorrentError, self.core.add_torrent_file, filename, False, options
+ )
@defer.inlineCallbacks
def test_add_torrent_url(self):
- url = 'http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent' % self.listen_port
+ url = (
+ 'http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent'
+ % self.listen_port
+ )
options = {}
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
@@ -340,7 +341,12 @@ class CoreTestCase(BaseTestCase):
self.assertEqual(len(self.core.get_session_state()), 0)
def test_remove_torrent_invalid(self):
- self.assertRaises(InvalidTorrentError, self.core.remove_torrent, 'torrentidthatdoesntexist', True)
+ self.assertRaises(
+ InvalidTorrentError,
+ self.core.remove_torrent,
+ 'torrentidthatdoesntexist',
+ True,
+ )
@defer.inlineCallbacks
def test_remove_torrents(self):
@@ -353,15 +359,19 @@ class CoreTestCase(BaseTestCase):
filename2 = common.get_test_data_file('unicode_filenames.torrent')
with open(filename2, 'rb') as _file:
filedump = b64encode(_file.read())
- torrent_id2 = yield self.core.add_torrent_file_async(filename2, filedump, options)
+ torrent_id2 = yield self.core.add_torrent_file_async(
+ filename2, filedump, options
+ )
d = self.core.remove_torrents([torrent_id, torrent_id2], True)
def test_ret(val):
self.assertTrue(val == [])
+
d.addCallback(test_ret)
def test_session_state(val):
self.assertEqual(len(self.core.get_session_state()), 0)
+
d.addCallback(test_session_state)
yield d
@@ -371,15 +381,24 @@ class CoreTestCase(BaseTestCase):
filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file:
filedump = b64encode(_file.read())
- torrent_id = yield self.core.add_torrent_file_async(filename, filedump, options)
- val = yield self.core.remove_torrents(['invalidid1', 'invalidid2', torrent_id], False)
+ torrent_id = yield self.core.add_torrent_file_async(
+ filename, filedump, options
+ )
+ val = yield self.core.remove_torrents(
+ ['invalidid1', 'invalidid2', torrent_id], False
+ )
self.assertEqual(len(val), 2)
- self.assertEqual(val[0], ('invalidid1', 'torrent_id invalidid1 not in session.'))
- self.assertEqual(val[1], ('invalidid2', 'torrent_id invalidid2 not in session.'))
+ self.assertEqual(
+ val[0], ('invalidid1', 'torrent_id invalidid1 not in session.')
+ )
+ self.assertEqual(
+ val[1], ('invalidid2', 'torrent_id invalidid2 not in session.')
+ )
def test_get_session_status(self):
status = self.core.get_session_status(
- ['net.recv_tracker_bytes', 'net.sent_tracker_bytes'])
+ ['net.recv_tracker_bytes', 'net.sent_tracker_bytes']
+ )
self.assertIsInstance(status, dict)
self.assertEqual(status['net.recv_tracker_bytes'], 0)
self.assertEqual(status['net.sent_tracker_bytes'], 0)
@@ -402,8 +421,7 @@ class CoreTestCase(BaseTestCase):
self.assertEqual(status['upload_rate'], 0)
def test_get_session_status_ratio(self):
- status = self.core.get_session_status([
- 'write_hit_ratio', 'read_hit_ratio'])
+ status = self.core.get_session_status(['write_hit_ratio', 'read_hit_ratio'])
self.assertIsInstance(status, dict)
self.assertEqual(status['write_hit_ratio'], 0.0)
self.assertEqual(status['read_hit_ratio'], 0.0)
@@ -438,14 +456,23 @@ class CoreTestCase(BaseTestCase):
}
for key in pathlist:
- self.assertEqual(deluge.core.torrent.sanitize_filepath(key, folder=False), pathlist[key])
- self.assertEqual(deluge.core.torrent.sanitize_filepath(key, folder=True), pathlist[key] + '/')
+ self.assertEqual(
+ deluge.core.torrent.sanitize_filepath(key, folder=False), pathlist[key]
+ )
+ self.assertEqual(
+ deluge.core.torrent.sanitize_filepath(key, folder=True),
+ pathlist[key] + '/',
+ )
def test_get_set_config_values(self):
- self.assertEqual(self.core.get_config_values(['abc', 'foo']), {'foo': None, 'abc': None})
+ self.assertEqual(
+ self.core.get_config_values(['abc', 'foo']), {'foo': None, 'abc': None}
+ )
self.assertEqual(self.core.get_config_value('foobar'), None)
self.core.set_config({'abc': 'def', 'foo': 10, 'foobar': 'barfoo'})
- self.assertEqual(self.core.get_config_values(['foo', 'abc']), {'foo': 10, 'abc': 'def'})
+ self.assertEqual(
+ self.core.get_config_values(['foo', 'abc']), {'foo': 10, 'abc': 'def'}
+ )
self.assertEqual(self.core.get_config_value('foobar'), 'barfoo')
def test_read_only_config_keys(self):
diff --git a/deluge/tests/test_error.py b/deluge/tests/test_error.py
index 24512c3ce..c552e9422 100644
--- a/deluge/tests/test_error.py
+++ b/deluge/tests/test_error.py
@@ -24,6 +24,7 @@ class ErrorTestCase(unittest.TestCase):
e = deluge.error.DelugeError(msg)
self.assertEqual(str(e), msg)
from twisted.internet.defer import DebugInfo
+
del DebugInfo.__del__ # Hides all errors
self.assertEqual(e._args, (msg,))
self.assertEqual(e._kwargs, {})
@@ -32,15 +33,19 @@ class ErrorTestCase(unittest.TestCase):
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,
+ 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
required_level = 10
e = deluge.error.NotAuthorizedError(current_level, required_level)
- self.assertEqual(str(e), 'Auth level too low: %d < %d' % (current_level, required_level))
+ self.assertEqual(
+ str(e), 'Auth level too low: %d < %d' % (current_level, required_level)
+ )
def test_bad_login_error(self):
message = 'Login failed'
diff --git a/deluge/tests/test_files_tab.py b/deluge/tests/test_files_tab.py
index 4d7cb2a3c..c99f7902c 100644
--- a/deluge/tests/test_files_tab.py
+++ b/deluge/tests/test_files_tab.py
@@ -28,6 +28,7 @@ try:
except ImportError as err:
libs_available = False
import traceback
+
traceback.print_exc()
setup_translations()
@@ -35,7 +36,6 @@ setup_translations()
@pytest.mark.gtkui
class FilesTabTestCase(BaseTestCase):
-
def set_up(self):
if libs_available is False:
raise unittest.SkipTest('GTKUI dependencies not available')
@@ -70,7 +70,6 @@ class FilesTabTestCase(BaseTestCase):
print('')
def verify_treestore(self, treestore, tree):
-
def _verify_treestore(itr, tree_values):
i = 0
while itr:
@@ -83,6 +82,7 @@ class FilesTabTestCase(BaseTestCase):
itr = treestore.iter_next(itr)
i += 1
return True
+
return _verify_treestore(treestore.get_iter_root(), tree)
def test_files_tab(self):
@@ -91,9 +91,14 @@ class FilesTabTestCase(BaseTestCase):
{'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')
+ self.filestab._on_torrentfilerenamed_event(
+ self.t_id, self.index, '2/test_100.txt'
+ )
- ret = self.verify_treestore(self.filestab.treestore, [['1/', [['test_10.txt']]], ['2/', [['test_100.txt']]]])
+ ret = self.verify_treestore(
+ self.filestab.treestore,
+ [['1/', [['test_10.txt']]], ['2/', [['test_100.txt']]]],
+ )
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
@@ -106,9 +111,14 @@ class FilesTabTestCase(BaseTestCase):
{'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')
+ self.filestab._on_torrentfilerenamed_event(
+ self.t_id, self.index, '1/1/test_100.txt'
+ )
- ret = self.verify_treestore(self.filestab.treestore, [['1/', [['1/', [['test_100.txt'], ['test_10.txt']]]]]])
+ ret = self.verify_treestore(
+ self.filestab.treestore,
+ [['1/', [['1/', [['test_100.txt'], ['test_10.txt']]]]]],
+ )
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
@@ -121,9 +131,13 @@ class FilesTabTestCase(BaseTestCase):
{'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')
+ self.filestab._on_torrentfilerenamed_event(
+ self.t_id, self.index, '1/test_100.txt'
+ )
- ret = self.verify_treestore(self.filestab.treestore, [['1/', [['test_100.txt'], ['test_10.txt']]]])
+ ret = self.verify_treestore(
+ self.filestab.treestore, [['1/', [['test_100.txt'], ['test_10.txt']]]]
+ )
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
@@ -134,15 +148,13 @@ class FilesTabTestCase(BaseTestCase):
{'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')
+ 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'],
- ],
- ]],
+ self.filestab.treestore,
+ [['1/', [['2/', [['test_100.txt']]], ['test_10.txt']]]],
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
@@ -156,9 +168,13 @@ class FilesTabTestCase(BaseTestCase):
{'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')
+ self.filestab._on_torrentfilerenamed_event(
+ self.t_id, self.index, '1/test_100.txt'
+ )
- ret = self.verify_treestore(self.filestab.treestore, [['1/', [['test_100.txt'], ['test_10.txt']]]])
+ ret = self.verify_treestore(
+ self.filestab.treestore, [['1/', [['test_100.txt'], ['test_10.txt']]]]
+ )
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
diff --git a/deluge/tests/test_httpdownloader.py b/deluge/tests/test_httpdownloader.py
index d917d45dd..e3746a1ad 100644
--- a/deluge/tests/test_httpdownloader.py
+++ b/deluge/tests/test_httpdownloader.py
@@ -33,26 +33,20 @@ def fname(name):
class RedirectResource(Resource):
-
def render(self, request):
url = self.get_url().encode('utf8')
return redirectTo(url, request)
class RenameResource(Resource):
-
def render(self, request):
filename = request.args.get(b'filename', [b'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
class AttachmentResource(Resource):
-
def render(self, request):
request.setHeader(b'Content-Type', b'text/plain')
request.setHeader(b'Content-Disposition', b'attachment')
@@ -60,7 +54,6 @@ class AttachmentResource(Resource):
class CookieResource(Resource):
-
def render(self, request):
request.setHeader(b'Content-Type', b'text/plain')
if request.getCookie(b'password') is None:
@@ -73,7 +66,6 @@ class CookieResource(Resource):
class GzipResource(Resource):
-
def render(self, request):
message = request.args.get(b'msg', [b'EFFICIENCY!'])[0]
request.setHeader(b'Content-Type', b'text/plain')
@@ -81,7 +73,6 @@ class GzipResource(Resource):
class PartialDownloadResource(Resource):
-
def __init__(self, *args, **kwargs):
Resource.__init__(self)
self.render_count = 0
@@ -126,7 +117,6 @@ class TopLevelResource(Resource):
class DownloadFileTestCase(unittest.TestCase):
-
def get_url(self, path=''):
return 'http://localhost:%d/%s' % (self.listen_port, path)
@@ -245,6 +235,7 @@ class DownloadFileTestCase(unittest.TestCase):
def cb(result):
print(result)
+
d.addCallback(self.assertNotContains, b'fail', file_mode='rb')
return d
@@ -255,6 +246,7 @@ class DownloadFileTestCase(unittest.TestCase):
def on_redirect(failure):
self.assertTrue(type(failure), PageRedirect)
+
d.addErrback(on_redirect)
return d
diff --git a/deluge/tests/test_json_api.py b/deluge/tests/test_json_api.py
index 68d7b6001..a8eaebda1 100644
--- a/deluge/tests/test_json_api.py
+++ b/deluge/tests/test_json_api.py
@@ -34,10 +34,11 @@ common.disable_new_release_check()
class JSONBase(BaseTestCase, DaemonBase):
-
def connect_client(self, *args, **kwargs):
return client.connect(
- 'localhost', self.listen_port, username=kwargs.get('user', ''),
+ 'localhost',
+ self.listen_port,
+ username=kwargs.get('user', ''),
password=kwargs.get('password', ''),
)
@@ -52,7 +53,6 @@ class JSONBase(BaseTestCase, DaemonBase):
class JSONTestCase(JSONBase):
-
def set_up(self):
d = self.common_set_up()
d.addCallback(self.start_core)
@@ -81,6 +81,7 @@ class JSONTestCase(JSONBase):
def compress(contents, request):
return contents
+
self.patch(deluge.ui.web.json_api, 'compress', compress)
def write(response_str):
@@ -88,7 +89,9 @@ class JSONTestCase(JSONBase):
response = json_lib.loads(response_str)
self.assertEqual(response['result'], None)
self.assertEqual(response['id'], None)
- self.assertEqual(response['error']['message'], 'JSONException: JSON not decodable')
+ self.assertEqual(
+ response['error']['message'], 'JSONException: JSON not decodable'
+ )
self.assertEqual(response['error']['code'], 5)
request.write = write
@@ -127,7 +130,6 @@ class JSONTestCase(JSONBase):
class JSONCustomUserTestCase(JSONBase):
-
def set_up(self):
d = self.common_set_up()
d.addCallback(self.start_core)
@@ -152,7 +154,6 @@ class JSONCustomUserTestCase(JSONBase):
class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
-
def set_up(self):
d = self.common_set_up()
custom_script = """
@@ -176,6 +177,7 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
def get_session_id(s_id):
return s_id
+
self.patch(deluge.ui.web.auth, 'get_session_id', get_session_id)
auth_conf = {'session_timeout': 10, 'sessions': {}}
auth = Auth(auth_conf)
@@ -195,12 +197,12 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
def on_error(error):
self.assertEqual(error.type, DelugeError)
+
result.addErrback(on_error)
yield result
class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
-
def set_up(self):
d = self.common_set_up()
custom_script = """
@@ -219,13 +221,17 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
daemon.rpcserver.register_object(test)
"""
from twisted.internet.defer import Deferred
+
extra_callback = {
- 'deferred': Deferred(), 'types': ['stderr'],
+ 'deferred': Deferred(),
+ 'types': ['stderr'],
'timeout': 10,
- 'triggers': [{
- 'expr': 'in test_raise_error',
- 'value': lambda reader, data, data_all: 'Test',
- }],
+ 'triggers': [
+ {
+ 'expr': 'in test_raise_error',
+ 'value': lambda reader, data, data_all: 'Test',
+ }
+ ],
}
def on_test_raise(*args):
@@ -234,8 +240,12 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
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],
+ 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
@@ -278,5 +288,6 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
def on_success(arg):
self.assertEqual(arg, server.NOT_DONE_YET)
return True
+
d.addCallbacks(on_success, self.fail)
yield d
diff --git a/deluge/tests/test_log.py b/deluge/tests/test_log.py
index fd65bbf6c..572693b7c 100644
--- a/deluge/tests/test_log.py
+++ b/deluge/tests/test_log.py
@@ -27,6 +27,7 @@ class LogTestCase(BaseTestCase):
def test_old_log_deprecation_warning(self):
from deluge.log import LOG
+
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter('always')
diff --git a/deluge/tests/test_maketorrent.py b/deluge/tests/test_maketorrent.py
index da008e876..4e0099653 100644
--- a/deluge/tests/test_maketorrent.py
+++ b/deluge/tests/test_maketorrent.py
@@ -19,10 +19,12 @@ from deluge.common import windows_check
def check_torrent(filename):
# Test loading with libtorrent to make sure it's valid
from deluge._libtorrent import lt
+
lt.torrent_info(filename)
# Test loading with our internal TorrentInfo class
from deluge.ui.common import TorrentInfo
+
TorrentInfo(filename)
diff --git a/deluge/tests/test_metafile.py b/deluge/tests/test_metafile.py
index 4a41a50ce..20b6b1056 100644
--- a/deluge/tests/test_metafile.py
+++ b/deluge/tests/test_metafile.py
@@ -19,10 +19,12 @@ from deluge.common import windows_check
def check_torrent(filename):
# Test loading with libtorrent to make sure it's valid
from deluge._libtorrent import lt
+
lt.torrent_info(filename)
# Test loading with our internal TorrentInfo class
from deluge.ui.common import TorrentInfo
+
TorrentInfo(filename)
diff --git a/deluge/tests/test_plugin_metadata.py b/deluge/tests/test_plugin_metadata.py
index 63bbb9ab5..436fc2c50 100644
--- a/deluge/tests/test_plugin_metadata.py
+++ b/deluge/tests/test_plugin_metadata.py
@@ -16,7 +16,6 @@ from .basetest import BaseTestCase
class PluginManagerBaseTestCase(BaseTestCase):
-
def set_up(self):
common.set_tmp_config_dir()
diff --git a/deluge/tests/test_rpcserver.py b/deluge/tests/test_rpcserver.py
index 0afcfd63b..02f9af023 100644
--- a/deluge/tests/test_rpcserver.py
+++ b/deluge/tests/test_rpcserver.py
@@ -31,7 +31,6 @@ class DelugeRPCProtocolTester(DelugeRPCProtocol):
class RPCServerTestCase(BaseTestCase):
-
def set_up(self):
self.rpcserver = RPCServer(listen=False)
self.rpcserver.factory.protocol = DelugeRPCProtocolTester
@@ -50,11 +49,13 @@ class RPCServerTestCase(BaseTestCase):
def tear_down(self):
def on_shutdown(result):
del self.rpcserver
+
return component.shutdown().addCallback(on_shutdown)
def test_emit_event_for_session_id(self):
torrent_id = '12'
from deluge.event import TorrentFolderRenamedEvent
+
data = [torrent_id, 'new name', 'old name']
e = TorrentFolderRenamedEvent(*data)
self.rpcserver.emit_event_for_session_id(self.session_id, e)
@@ -72,7 +73,9 @@ class RPCServerTestCase(BaseTestCase):
def test_valid_client_login(self):
self.authmanager = AuthManager()
auth = get_localhost_auth()
- self.protocol.dispatch(self.request_id, 'daemon.login', auth, {'client_version': 'Test'})
+ self.protocol.dispatch(
+ self.request_id, 'daemon.login', auth, {'client_version': 'Test'}
+ )
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_RESPONSE, str(msg))
self.assertEqual(msg[1], self.request_id, str(msg))
@@ -80,10 +83,12 @@ class RPCServerTestCase(BaseTestCase):
def test_client_login_error(self):
# This test causes error log prints while running the test...
- self.protocol.transport = None # This should cause AttributeError
+ self.protocol.transport = None # This should cause AttributeError
self.authmanager = AuthManager()
auth = get_localhost_auth()
- self.protocol.dispatch(self.request_id, 'daemon.login', auth, {'client_version': 'Test'})
+ self.protocol.dispatch(
+ self.request_id, 'daemon.login', auth, {'client_version': 'Test'}
+ )
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_ERROR)
self.assertEqual(msg[1], self.request_id)
diff --git a/deluge/tests/test_security.py b/deluge/tests/test_security.py
index ff6a3e83b..379404906 100644
--- a/deluge/tests/test_security.py
+++ b/deluge/tests/test_security.py
@@ -49,7 +49,8 @@ class SecurityBaseTestCase(object):
'0',
test,
'127.0.0.1:%d' % self.port,
- ])
+ ],
+ )
def on_result(results):
@@ -162,7 +163,6 @@ class DaemonSecurityTestCase(BaseTestCase, DaemonBase, SecurityBaseTestCase):
@pytest.mark.security
class WebUISecurityTestBase(WebServerTestBase, SecurityBaseTestCase):
-
def __init__(self, testname):
super(WebUISecurityTestBase, self).__init__(testname)
SecurityBaseTestCase.__init__(self)
diff --git a/deluge/tests/test_sessionproxy.py b/deluge/tests/test_sessionproxy.py
index 5f2ea4f84..03f3cc27e 100644
--- a/deluge/tests/test_sessionproxy.py
+++ b/deluge/tests/test_sessionproxy.py
@@ -19,7 +19,6 @@ from .basetest import BaseTestCase
class Core(object):
-
def __init__(self):
self.reset()
@@ -48,7 +47,10 @@ class Core(object):
ret = {}
if torrent_id in self.prev_status:
for key in keys:
- if self.prev_status[torrent_id][key] != self.torrents[torrent_id][key]:
+ if (
+ self.prev_status[torrent_id][key]
+ != self.torrents[torrent_id][key]
+ ):
ret[key] = self.torrents[torrent_id][key]
else:
ret = self.torrents[torrent_id]
@@ -77,7 +79,10 @@ class Core(object):
ret[torrent] = {}
if torrent in self.prev_status:
for key in self.prev_status[torrent]:
- if self.prev_status[torrent][key] != self.torrents[torrent][key]:
+ if (
+ self.prev_status[torrent][key]
+ != self.torrents[torrent][key]
+ ):
ret[torrent][key] = self.torrents[torrent][key]
else:
ret[torrent] = dict(self.torrents[torrent])
@@ -101,7 +106,6 @@ client = Client()
class SessionProxyTestCase(BaseTestCase):
-
def set_up(self):
self.clock = Clock()
self.patch(deluge.ui.sessionproxy, 'time', self.clock.seconds)
@@ -115,6 +119,7 @@ class SessionProxyTestCase(BaseTestCase):
# Advance clock to expire the cache times
self.clock.advance(2)
return self.sp.get_torrents_status({'id': torrent_ids}, inital_keys)
+
d.addCallback(do_get_torrents_status)
return d
diff --git a/deluge/tests/test_torrent.py b/deluge/tests/test_torrent.py
index 39cd47554..4d028fda9 100644
--- a/deluge/tests/test_torrent.py
+++ b/deluge/tests/test_torrent.py
@@ -30,11 +30,11 @@ from .basetest import BaseTestCase
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,
+ 'core.conf',
+ defaults=deluge.core.preferencesmanager.DEFAULT_PREFS,
config_dir=config_dir,
)
core_config.save()
@@ -82,12 +82,38 @@ class TorrentTestCase(BaseTestCase):
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,
+ 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)
+ 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):
+ def run_test_set_prioritize_first_last_pieces(
+ self, torrent_file, prioritized_piece_indexes
+ ):
atp = self.get_torrent_atp(torrent_file)
handle = self.session.add_torrent(atp)
@@ -167,21 +193,47 @@ class TorrentTestCase(BaseTestCase):
if windows_check():
raise unittest.SkipTest('unexpected end of file in bencoded string')
resume_data = {
- 'active_time': 13399, 'num_incomplete': 16777215, 'announce_to_lsd': 1, 'seed_mode': 0,
- 'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01', 'paused': 0,
- 'seeding_time': 13399, 'last_scrape': 13399,
- 'info-hash': '-\xc5\xd0\xe7\x1af\xfeid\x9ad\r9\xcb\x00\xa2YpIs', 'max_uploads': 16777215,
- 'max_connections': 16777215, 'num_downloaders': 16777215, 'total_downloaded': 0,
- 'file-format': 'libtorrent resume file', 'peers6': '', 'added_time': 1411826665,
- 'banned_peers6': '', 'file_priority': [1], 'last_seen_complete': 0, 'total_uploaded': 0,
+ 'active_time': 13399,
+ 'num_incomplete': 16777215,
+ 'announce_to_lsd': 1,
+ 'seed_mode': 0,
+ 'pieces': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01',
+ 'paused': 0,
+ 'seeding_time': 13399,
+ 'last_scrape': 13399,
+ 'info-hash': '-\xc5\xd0\xe7\x1af\xfeid\x9ad\r9\xcb\x00\xa2YpIs',
+ 'max_uploads': 16777215,
+ 'max_connections': 16777215,
+ 'num_downloaders': 16777215,
+ 'total_downloaded': 0,
+ 'file-format': 'libtorrent resume file',
+ 'peers6': '',
+ 'added_time': 1411826665,
+ 'banned_peers6': '',
+ 'file_priority': [1],
+ 'last_seen_complete': 0,
+ 'total_uploaded': 0,
'piece_priority': '\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01',
- 'file-version': 1, 'announce_to_dht': 1, 'auto_managed': 1, 'upload_rate_limit': 0,
- 'completed_time': 1411826665, 'allocation': 'sparse', 'blocks per piece': 2,
- 'download_rate_limit': 0, 'libtorrent-version': '0.16.17.0', 'banned_peers': '',
- '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-version': 1,
+ 'announce_to_dht': 1,
+ 'auto_managed': 1,
+ 'upload_rate_limit': 0,
+ 'completed_time': 1411826665,
+ 'allocation': 'sparse',
+ 'blocks per piece': 2,
+ 'download_rate_limit': 0,
+ 'libtorrent-version': '0.16.17.0',
+ 'banned_peers': '',
+ '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,
}
torrent_state = TorrentState(
torrent_id='2dc5d0e71a66fe69649a640d39cb00a259704973',
@@ -197,13 +249,15 @@ 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():
self.assert_state(torrent, 'Error')
- tm_resume_data = lt.bdecode(self.core.torrentmanager.resume_data[torrent.torrent_id])
+ tm_resume_data = lt.bdecode(
+ self.core.torrentmanager.resume_data[torrent.torrent_id]
+ )
self.assertEqual(tm_resume_data, resume_data)
return deferLater(reactor, 0.5, assert_resume_data)
@@ -224,10 +278,7 @@ class TorrentTestCase(BaseTestCase):
# Test finished and uploading but no stop_at_ratio set.
self.assertEqual(self.torrent.get_eta(), 0)
- self.torrent.options = {
- 'stop_at_ratio': True,
- 'stop_ratio': 1.5,
- }
+ self.torrent.options = {'stop_at_ratio': True, 'stop_ratio': 1.5}
result = self.torrent.get_eta()
self.assertEqual(result, 2)
self.assertIsInstance(result, int)
diff --git a/deluge/tests/test_torrentmanager.py b/deluge/tests/test_torrentmanager.py
index 711f778c2..0aacea41c 100644
--- a/deluge/tests/test_torrentmanager.py
+++ b/deluge/tests/test_torrentmanager.py
@@ -28,7 +28,6 @@ warnings.resetwarnings()
class TorrentmanagerTestCase(BaseTestCase):
-
def set_up(self):
common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
@@ -40,7 +39,6 @@ class TorrentmanagerTestCase(BaseTestCase):
return component.start()
def tear_down(self):
-
def on_shutdown(result):
del self.rpcserver
del self.core
@@ -53,18 +51,20 @@ class TorrentmanagerTestCase(BaseTestCase):
with open(filename, 'rb') as _file:
filedump = _file.read()
torrent_id = yield self.core.add_torrent_file_async(
- filename, b64encode(filedump), {})
+ filename, b64encode(filedump), {}
+ )
self.assertTrue(self.tm.remove(torrent_id, False))
def test_prefetch_metadata(self):
from deluge._libtorrent import lt
+
with open(common.get_test_data_file('test.torrent'), 'rb') as _file:
t_info = lt.torrent_info(lt.bdecode(_file.read()))
mock_alert = mock.MagicMock()
mock_alert.handle.info_hash = mock.MagicMock(
- return_value='ab570cdd5a17ea1b61e970bb72047de141bce173')
- mock_alert.handle.get_torrent_info = mock.MagicMock(
- return_value=t_info)
+ return_value='ab570cdd5a17ea1b61e970bb72047de141bce173'
+ )
+ mock_alert.handle.get_torrent_info = mock.MagicMock(return_value=t_info)
magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173'
d = self.tm.prefetch_metadata(magnet, 30)
@@ -72,34 +72,36 @@ class TorrentmanagerTestCase(BaseTestCase):
expected = (
'ab570cdd5a17ea1b61e970bb72047de141bce173',
- bencode({
- 'piece length': 32768,
- 'sha1': (
- b'2\xce\xb6\xa8"\xd7\xf0\xd4\xbf\xdc^K\xba\x1bh'
- b'\x9d\xc5\xb7\xac\xdd'
- ),
- 'name': 'azcvsupdater_2.6.2.jar',
- 'private': 0,
- 'pieces': (
- b'\xdb\x04B\x05\xc3\'\xdab\xb8su97\xa9u'
- b'\xca<w\\\x1ef\xd4\x9b\x16\xa9}\xc0\x9f:\xfd'
- b'\x97qv\x83\xa2"\xef\x9d7\x0by!\rl\xe5v\xb7'
- b'\x18{\xf7/"P\xe9\x8d\x01D\x9e8\xbd\x16\xe3'
- b'\xfb-\x9d\xaa\xbcM\x11\xba\x92\xfc\x13F\xf0'
- b'\x1c\x86x+\xc8\xd0S\xa9\x90`\xa1\xe4\x82\xe8'
- b'\xfc\x08\xf7\xe3\xe5\xf6\x85\x1c%\xe7%\n\xed'
- b'\xc0\x1f\xa1;\x9a\xea\xcf\x90\x0c/F>\xdf\xdagA'
- b'\xc42|\xda\x82\xf5\xa6b\xa1\xb8#\x80wI\xd8f'
- b'\xf8\xbd\xacW\xab\xc3s\xe0\xbbw\xf2K\xbe\xee'
- b'\xa8rG\xe1W\xe8\xb7\xc2i\xf3\xd8\xaf\x9d\xdc'
- b'\xd0#\xf4\xc1\x12u\xcd\x0bE?:\xe8\x9c\x1cu'
- b'\xabb(oj\r^\xd5\xd5A\x83\x88\x9a\xa1J\x1c?'
- b'\xa1\xd6\x8c\x83\x9e&'
- ),
- 'length': 307949,
- 'name.utf-8': b'azcvsupdater_2.6.2.jar',
- 'ed2k': b'>p\xefl\xfa]\x95K\x1b^\xc2\\;;e\xb7',
- }),
+ bencode(
+ {
+ 'piece length': 32768,
+ 'sha1': (
+ b'2\xce\xb6\xa8"\xd7\xf0\xd4\xbf\xdc^K\xba\x1bh'
+ b'\x9d\xc5\xb7\xac\xdd'
+ ),
+ 'name': 'azcvsupdater_2.6.2.jar',
+ 'private': 0,
+ 'pieces': (
+ b'\xdb\x04B\x05\xc3\'\xdab\xb8su97\xa9u'
+ b'\xca<w\\\x1ef\xd4\x9b\x16\xa9}\xc0\x9f:\xfd'
+ b'\x97qv\x83\xa2"\xef\x9d7\x0by!\rl\xe5v\xb7'
+ b'\x18{\xf7/"P\xe9\x8d\x01D\x9e8\xbd\x16\xe3'
+ b'\xfb-\x9d\xaa\xbcM\x11\xba\x92\xfc\x13F\xf0'
+ b'\x1c\x86x+\xc8\xd0S\xa9\x90`\xa1\xe4\x82\xe8'
+ b'\xfc\x08\xf7\xe3\xe5\xf6\x85\x1c%\xe7%\n\xed'
+ b'\xc0\x1f\xa1;\x9a\xea\xcf\x90\x0c/F>\xdf\xdagA'
+ b'\xc42|\xda\x82\xf5\xa6b\xa1\xb8#\x80wI\xd8f'
+ b'\xf8\xbd\xacW\xab\xc3s\xe0\xbbw\xf2K\xbe\xee'
+ b'\xa8rG\xe1W\xe8\xb7\xc2i\xf3\xd8\xaf\x9d\xdc'
+ b'\xd0#\xf4\xc1\x12u\xcd\x0bE?:\xe8\x9c\x1cu'
+ b'\xabb(oj\r^\xd5\xd5A\x83\x88\x9a\xa1J\x1c?'
+ b'\xa1\xd6\x8c\x83\x9e&'
+ ),
+ 'length': 307949,
+ 'name.utf-8': b'azcvsupdater_2.6.2.jar',
+ 'ed2k': b'>p\xefl\xfa]\x95K\x1b^\xc2\\;;e\xb7',
+ }
+ ),
)
self.assertEqual(expected, self.successResultOf(d))
@@ -117,4 +119,5 @@ class TorrentmanagerTestCase(BaseTestCase):
def test_remove_invalid_torrent(self):
self.assertRaises(
- InvalidTorrentError, self.tm.remove, 'torrentidthatdoesntexist')
+ InvalidTorrentError, self.tm.remove, 'torrentidthatdoesntexist'
+ )
diff --git a/deluge/tests/test_torrentview.py b/deluge/tests/test_torrentview.py
index 9cf9ce282..3badb20da 100644
--- a/deluge/tests/test_torrentview.py
+++ b/deluge/tests/test_torrentview.py
@@ -27,10 +27,13 @@ except ImportError as err:
libs_available = False
TYPE_UINT64 = 'Whatever'
import traceback
+
traceback.print_exc()
else:
libs_available = True
- from deluge.ui.gtkui.mainwindow import MainWindow # pylint: disable=ungrouped-imports
+ from deluge.ui.gtkui.mainwindow import (
+ MainWindow,
+ ) # pylint: disable=ungrouped-imports
from deluge.ui.gtkui.menubar import MenuBar
from deluge.ui.gtkui.torrentdetails import TorrentDetails
from deluge.ui.gtkui.torrentview import TorrentView
@@ -43,27 +46,66 @@ setup_translations()
class TorrentviewTestCase(BaseTestCase):
default_column_index = [
- 'filter', 'torrent_id', 'dirty', '#',
+ 'filter',
+ 'torrent_id',
+ 'dirty',
+ '#',
'Name',
- 'Size', 'Downloaded', 'Uploaded', 'Remaining',
+ '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',
+ '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,
+ 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
@@ -84,9 +126,16 @@ class TorrentviewTestCase(BaseTestCase):
def test_torrentview_columns(self):
- self.assertEqual(self.torrentview.column_index, TorrentviewTestCase.default_column_index)
- self.assertEqual(self.torrentview.liststore_columns, TorrentviewTestCase.default_liststore_columns)
- self.assertEqual(self.torrentview.columns['Download Folder'].column_indices, [29])
+ self.assertEqual(
+ self.torrentview.column_index, TorrentviewTestCase.default_column_index
+ )
+ self.assertEqual(
+ self.torrentview.liststore_columns,
+ TorrentviewTestCase.default_liststore_columns,
+ )
+ self.assertEqual(
+ self.torrentview.columns['Download Folder'].column_indices, [29]
+ )
def test_add_column(self):
@@ -137,10 +186,24 @@ class TorrentviewTestCase(BaseTestCase):
self.torrentview.add_text_column(test_col, status_field=['label'])
self.torrentview.remove_column(test_col)
- self.assertEqual(len(self.torrentview.liststore_columns), len(TorrentviewTestCase.default_liststore_columns))
- self.assertEqual(len(self.torrentview.column_index), len(TorrentviewTestCase.default_column_index))
- self.assertEqual(self.torrentview.column_index[-1], TorrentviewTestCase.default_column_index[-1])
- self.assertEqual(self.torrentview.columns[TorrentviewTestCase.default_column_index[-1]].column_indices, [31])
+ self.assertEqual(
+ len(self.torrentview.liststore_columns),
+ len(TorrentviewTestCase.default_liststore_columns),
+ )
+ self.assertEqual(
+ len(self.torrentview.column_index),
+ len(TorrentviewTestCase.default_column_index),
+ )
+ self.assertEqual(
+ self.torrentview.column_index[-1],
+ TorrentviewTestCase.default_column_index[-1],
+ )
+ self.assertEqual(
+ self.torrentview.columns[
+ TorrentviewTestCase.default_column_index[-1]
+ ].column_indices,
+ [31],
+ )
def test_remove_columns(self):
@@ -165,16 +228,32 @@ class TorrentviewTestCase(BaseTestCase):
# Remove test_col2
self.torrentview.remove_column(test_col2)
- self.assertEqual(len(self.torrentview.liststore_columns), len(TorrentviewTestCase.default_liststore_columns))
- self.assertEqual(len(self.torrentview.column_index), len(TorrentviewTestCase.default_column_index))
- self.assertEqual(self.torrentview.column_index[-1], TorrentviewTestCase.default_column_index[-1])
- self.assertEqual(self.torrentview.columns[TorrentviewTestCase.default_column_index[-1]].column_indices, [31])
+ self.assertEqual(
+ len(self.torrentview.liststore_columns),
+ len(TorrentviewTestCase.default_liststore_columns),
+ )
+ self.assertEqual(
+ len(self.torrentview.column_index),
+ len(TorrentviewTestCase.default_column_index),
+ )
+ self.assertEqual(
+ self.torrentview.column_index[-1],
+ TorrentviewTestCase.default_column_index[-1],
+ )
+ self.assertEqual(
+ self.torrentview.columns[
+ TorrentviewTestCase.default_column_index[-1]
+ ].column_indices,
+ [31],
+ )
def test_add_remove_column_multiple_types(self):
# 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.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,
@@ -189,7 +268,21 @@ class TorrentviewTestCase(BaseTestCase):
# Remove multiple column-types column
self.torrentview.remove_column(test_col3)
- self.assertEqual(len(self.torrentview.liststore_columns), len(TorrentviewTestCase.default_liststore_columns))
- self.assertEqual(len(self.torrentview.column_index), len(TorrentviewTestCase.default_column_index))
- self.assertEqual(self.torrentview.column_index[-1], TorrentviewTestCase.default_column_index[-1])
- self.assertEqual(self.torrentview.columns[TorrentviewTestCase.default_column_index[-1]].column_indices, [31])
+ self.assertEqual(
+ len(self.torrentview.liststore_columns),
+ len(TorrentviewTestCase.default_liststore_columns),
+ )
+ self.assertEqual(
+ len(self.torrentview.column_index),
+ len(TorrentviewTestCase.default_column_index),
+ )
+ self.assertEqual(
+ self.torrentview.column_index[-1],
+ TorrentviewTestCase.default_column_index[-1],
+ )
+ self.assertEqual(
+ self.torrentview.columns[
+ TorrentviewTestCase.default_column_index[-1]
+ ].column_indices,
+ [31],
+ )
diff --git a/deluge/tests/test_transfer.py b/deluge/tests/test_transfer.py
index cc13cef93..b7e0e8388 100644
--- a/deluge/tests/test_transfer.py
+++ b/deluge/tests/test_transfer.py
@@ -21,7 +21,6 @@ deluge.log.setup_logger('none')
class TransferTestClass(DelugeTransferProtocol):
-
def __init__(self):
DelugeTransferProtocol.__init__(self)
self.transport = self
@@ -57,6 +56,7 @@ class TransferTestClass(DelugeTransferProtocol):
"""
import zlib
+
print('\n=== New Data Received ===\nBytes received:', len(data))
if self._buffer:
@@ -87,15 +87,23 @@ class TransferTestClass(DelugeTransferProtocol):
try:
request = rencode.loads(dobj.decompress(data))
print('Successfully loaded message', end=' ')
- print(' - Buffer length: %d, data length: %d, unused length: %d' %
- (len(data), len(data) - len(dobj.unused_data), len(dobj.unused_data)))
+ print(
+ ' - Buffer length: %d, data length: %d, unused length: %d'
+ % (
+ len(data),
+ len(data) - len(dobj.unused_data),
+ len(dobj.unused_data),
+ )
+ )
print('Packet count:', self.packet_count)
except Exception as ex:
# log.debug('Received possible invalid message (%r): %s', data, e)
# This could be cut-off data, so we'll save this in the buffer
# and try to prepend it on the next dataReceived()
self._buffer = data
- print('Failed to load buffer (size %d): %s' % (len(self._buffer), str(ex)))
+ print(
+ 'Failed to load buffer (size %d): %s' % (len(self._buffer), str(ex))
+ )
return
else:
data = dobj.unused_data
@@ -105,7 +113,6 @@ class TransferTestClass(DelugeTransferProtocol):
class DelugeTransferProtocolTestCase(unittest.TestCase):
-
def setUp(self): # NOQA: N803
"""
The expected messages corresponds to the test messages (msg1, msg2) after they've been processed
@@ -117,9 +124,17 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
"""
self.transfer = TransferTestClass()
- self.msg1 = (0, 1, {'key_int': 1242429423}, {'key_str': b'some string'}, {'key_bool': True})
+ self.msg1 = (
+ 0,
+ 1,
+ {'key_int': 1242429423},
+ {'key_str': b'some string'},
+ {'key_bool': True},
+ )
self.msg2 = (
- 2, 3, {'key_float': 12424.29423},
+ 2,
+ 3,
+ {'key_float': 12424.29423},
{'key_unicode': 'some string'},
{'key_dict_with_tuple': {'key_tuple': (1, 2, 3)}},
{'keylist': [4, '5', 6.7]},
@@ -153,7 +168,9 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
method 'message_received'.
"""
- self.transfer.dataReceived(base64.b64decode(self.msg1_expected_compressed_base64))
+ self.transfer.dataReceived(
+ base64.b64decode(self.msg1_expected_compressed_base64)
+ )
# Get the data as sent by DelugeTransferProtocol
messages = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(messages))
@@ -174,8 +191,9 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
and lets DelugeTransferProtocol receive the data as one string.
"""
- two_concatenated = base64.b64decode(self.msg1_expected_compressed_base64) + \
- base64.b64decode(self.msg2_expected_compressed_base64)
+ two_concatenated = base64.b64decode(
+ self.msg1_expected_compressed_base64
+ ) + base64.b64decode(self.msg2_expected_compressed_base64)
self.transfer.dataReceived(two_concatenated)
# Get the data as sent by DelugeTransferProtocol
@@ -190,16 +208,22 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
and lets DelugeTransferProtocol receive the data in multiple parts.
"""
- msg_bytes = base64.b64decode(self.msg1_expected_compressed_base64) + \
- base64.b64decode(self.msg2_expected_compressed_base64) + \
+ msg_bytes = (
base64.b64decode(self.msg1_expected_compressed_base64)
+ + base64.b64decode(self.msg2_expected_compressed_base64)
+ + base64.b64decode(self.msg1_expected_compressed_base64)
+ )
packet_size = 40
- one_message_byte_count = len(base64.b64decode(self.msg1_expected_compressed_base64))
- two_messages_byte_count = one_message_byte_count + \
- len(base64.b64decode(self.msg2_expected_compressed_base64))
- three_messages_byte_count = two_messages_byte_count + \
- len(base64.b64decode(self.msg1_expected_compressed_base64))
+ one_message_byte_count = len(
+ base64.b64decode(self.msg1_expected_compressed_base64)
+ )
+ two_messages_byte_count = one_message_byte_count + len(
+ base64.b64decode(self.msg2_expected_compressed_base64)
+ )
+ three_messages_byte_count = two_messages_byte_count + len(
+ base64.b64decode(self.msg1_expected_compressed_base64)
+ )
for d in self.receive_parts_helper(msg_bytes, packet_size):
bytes_received = self.transfer.get_bytes_recv()
@@ -213,7 +237,9 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
else:
expected_msgs_received_count = 0
# Verify that the expected number of complete messages has arrived
- self.assertEqual(expected_msgs_received_count, len(self.transfer.get_messages_in()))
+ self.assertEqual(
+ expected_msgs_received_count, len(self.transfer.get_messages_in())
+ )
# Get the data as received by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
@@ -230,28 +256,45 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
This test tries to test the protocol that relies on errors from rencode.
"""
- msg_bytes = base64.b64decode(self.msg1_expected_compressed_base64) + \
- base64.b64decode(self.msg2_expected_compressed_base64) + \
+ msg_bytes = (
base64.b64decode(self.msg1_expected_compressed_base64)
+ + base64.b64decode(self.msg2_expected_compressed_base64)
+ + base64.b64decode(self.msg1_expected_compressed_base64)
+ )
packet_size = 149
- one_message_byte_count = len(base64.b64decode(self.msg1_expected_compressed_base64))
- two_messages_byte_count = one_message_byte_count + \
- len(base64.b64decode(self.msg2_expected_compressed_base64))
- three_messages_byte_count = two_messages_byte_count + \
- len(base64.b64decode(self.msg1_expected_compressed_base64))
+ one_message_byte_count = len(
+ base64.b64decode(self.msg1_expected_compressed_base64)
+ )
+ two_messages_byte_count = one_message_byte_count + len(
+ base64.b64decode(self.msg2_expected_compressed_base64)
+ )
+ three_messages_byte_count = two_messages_byte_count + len(
+ base64.b64decode(self.msg1_expected_compressed_base64)
+ )
print()
- print('Msg1 size:', len(base64.b64decode(self.msg1_expected_compressed_base64)) - 4)
- print('Msg2 size:', len(base64.b64decode(self.msg2_expected_compressed_base64)) - 4)
- print('Msg3 size:', len(base64.b64decode(self.msg1_expected_compressed_base64)) - 4)
+ print(
+ 'Msg1 size:',
+ len(base64.b64decode(self.msg1_expected_compressed_base64)) - 4,
+ )
+ print(
+ 'Msg2 size:',
+ len(base64.b64decode(self.msg2_expected_compressed_base64)) - 4,
+ )
+ print(
+ 'Msg3 size:',
+ len(base64.b64decode(self.msg1_expected_compressed_base64)) - 4,
+ )
print('one_message_byte_count:', one_message_byte_count)
print('two_messages_byte_count:', two_messages_byte_count)
print('three_messages_byte_count:', three_messages_byte_count)
- for d in self.receive_parts_helper(msg_bytes, packet_size, self.transfer.data_received_old_protocol):
+ for d in self.receive_parts_helper(
+ msg_bytes, packet_size, self.transfer.data_received_old_protocol
+ ):
bytes_received = self.transfer.get_bytes_recv()
if bytes_received >= three_messages_byte_count:
@@ -264,8 +307,13 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
expected_msgs_received_count = 0
# Verify that the expected number of complete messages has arrived
if expected_msgs_received_count != len(self.transfer.get_messages_in()):
- print('Expected number of messages received is %d, but %d have been received.' %
- (expected_msgs_received_count, len(self.transfer.get_messages_in())))
+ print(
+ 'Expected number of messages received is %d, but %d have been received.'
+ % (
+ expected_msgs_received_count,
+ len(self.transfer.get_messages_in()),
+ )
+ )
# Get the data as received by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
@@ -287,18 +335,19 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
to read and parse the size of the payload.
"""
- two_concatenated = base64.b64decode(self.msg1_expected_compressed_base64) + \
- base64.b64decode(self.msg2_expected_compressed_base64)
+ two_concatenated = base64.b64decode(
+ self.msg1_expected_compressed_base64
+ ) + base64.b64decode(self.msg2_expected_compressed_base64)
first_len = len(base64.b64decode(self.msg1_expected_compressed_base64))
# Now found the entire first message, and half the header of the next message (2 bytes into the header)
- self.transfer.dataReceived(two_concatenated[:first_len + 2])
+ self.transfer.dataReceived(two_concatenated[: first_len + 2])
# Should be 1 message in the list
self.assertEqual(1, len(self.transfer.get_messages_in()))
# Send the rest
- self.transfer.dataReceived(two_concatenated[first_len + 2:])
+ self.transfer.dataReceived(two_concatenated[first_len + 2 :])
# Should be 2 messages in the list
self.assertEqual(2, len(self.transfer.get_messages_in()))
diff --git a/deluge/tests/test_ui_common.py b/deluge/tests/test_ui_common.py
index 20e0818c3..2ccdc1cc9 100644
--- a/deluge/tests/test_ui_common.py
+++ b/deluge/tests/test_ui_common.py
@@ -17,7 +17,6 @@ from . import common
class UICommonTestCase(unittest.TestCase):
-
def setUp(self): # NOQA: N803
pass
@@ -40,13 +39,15 @@ class UICommonTestCase(unittest.TestCase):
(
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,
+ ).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,
+ ).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)
@@ -54,5 +55,6 @@ class UICommonTestCase(unittest.TestCase):
(
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,
+ ).decode('utf8')
+ in files
)
diff --git a/deluge/tests/test_ui_console_fields.py b/deluge/tests/test_ui_console_fields.py
index 05d7132ec..2d4f4d300 100644
--- a/deluge/tests/test_ui_console_fields.py
+++ b/deluge/tests/test_ui_console_fields.py
@@ -13,14 +13,12 @@ from deluge.ui.console.widgets.fields import TextInput
class Parent(object):
-
def __init__(self):
self.border_off_x = 1
self.pane_width = 20
class UICommonTestCase(unittest.TestCase):
-
def setUp(self): # NOQA: N803
self.parent = Parent()
@@ -32,5 +30,13 @@ class UICommonTestCase(unittest.TestCase):
self._cursor_row = r
self._cursor_col = c
- t = TextInput(self.parent, 'name', 'message', move_func, 20, '/text/field/file/path', complete=False)
+ t = TextInput(
+ self.parent,
+ 'name',
+ 'message',
+ move_func,
+ 20,
+ '/text/field/file/path',
+ complete=False,
+ )
self.assertTrue(t) # Shut flake8 up (unused variable)
diff --git a/deluge/tests/test_ui_entry.py b/deluge/tests/test_ui_entry.py
index 39a0b7b50..8a032a26c 100644
--- a/deluge/tests/test_ui_entry.py
+++ b/deluge/tests/test_ui_entry.py
@@ -45,6 +45,7 @@ sys_stdout = sys.stdout
class StringFileDescriptor(object):
"""File descriptor that writes to string buffer"""
+
def __init__(self, fd):
self.out = StringIO()
self.fd = fd
@@ -63,7 +64,6 @@ class StringFileDescriptor(object):
class UIBaseTestCase(object):
-
def __init__(self):
self.var = {}
@@ -139,7 +139,13 @@ class DelugeEntryTestCase(BaseTestCase):
def test_start_with_log_level(self):
_level = []
- def setup_logger(level='error', filename=None, filemode='w', logrotate=None, output_stream=sys.stdout):
+ def setup_logger(
+ level='error',
+ filename=None,
+ filemode='w',
+ logrotate=None,
+ output_stream=sys.stdout,
+ ):
_level.append(level)
self.patch(deluge.log, 'setup_logger', setup_logger)
@@ -163,13 +169,13 @@ class GtkUIBaseTestCase(UIBaseTestCase):
self.patch(sys, 'argv', utf8_encode_structure(self.var['sys_arg_cmd']))
from deluge.ui.gtkui import gtkui
+
with mock.patch.object(gtkui.GtkUI, 'start', autospec=True):
self.exec_command()
@pytest.mark.gtkui
class GtkUIDelugeScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
-
def __init__(self, testname):
super(GtkUIDelugeScriptEntryTestCase, self).__init__(testname)
GtkUIBaseTestCase.__init__(self)
@@ -187,11 +193,11 @@ class GtkUIDelugeScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
@pytest.mark.gtkui
class GtkUIScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
-
def __init__(self, testname):
super(GtkUIScriptEntryTestCase, self).__init__(testname)
GtkUIBaseTestCase.__init__(self)
from deluge.ui import gtkui
+
self.var['cmd_name'] = 'deluge-gtk'
self.var['start_cmd'] = gtkui.start
self.var['sys_arg_cmd'] = ['./deluge-gtk']
@@ -220,7 +226,13 @@ class WebUIBaseTestCase(UIBaseTestCase):
def test_start_web_with_log_level(self):
_level = []
- def setup_logger(level='error', filename=None, filemode='w', logrotate=None, output_stream=sys.stdout):
+ def setup_logger(
+ level='error',
+ filename=None,
+ filemode='w',
+ logrotate=None,
+ output_stream=sys.stdout,
+ ):
_level.append(level)
self.patch(deluge.log, 'setup_logger', setup_logger)
@@ -284,7 +296,13 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
def test_start_console_with_log_level(self):
_level = []
- def setup_logger(level='error', filename=None, filemode='w', logrotate=None, output_stream=sys.stdout):
+ def setup_logger(
+ level='error',
+ filename=None,
+ filemode='w',
+ logrotate=None,
+ output_stream=sys.stdout,
+ ):
_level.append(level)
self.patch(deluge.log, 'setup_logger', setup_logger)
@@ -308,11 +326,18 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.assertRaises(SystemExit, self.exec_command)
std_output = fd.out.getvalue()
- self.assertTrue(('usage: %s' % self.var['cmd_name']) in std_output) # Check command name
+ self.assertTrue(
+ ('usage: %s' % self.var['cmd_name']) in std_output
+ ) # Check command name
self.assertTrue('Common Options:' in std_output)
self.assertTrue('Console Options:' in std_output)
- self.assertTrue('Console Commands:\n The following console commands are available:' in std_output)
- self.assertTrue('The following console commands are available:' in std_output)
+ self.assertTrue(
+ 'Console Commands:\n The following console commands are available:'
+ in std_output
+ )
+ self.assertTrue(
+ 'The following console commands are available:' in std_output
+ )
def test_console_command_info(self):
self.patch(sys, 'argv', self.var['sys_arg_cmd'] + ['info'])
@@ -334,7 +359,9 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
self.assertTrue('Show information about the torrents' in std_output)
def test_console_unrecognized_arguments(self):
- self.patch(sys, 'argv', ['./deluge', '--ui', 'console']) # --ui is not longer supported
+ self.patch(
+ sys, 'argv', ['./deluge', '--ui', 'console']
+ ) # --ui is not longer supported
fd = StringFileDescriptor(sys.stdout)
self.patch(argparse._sys, 'stderr', fd)
with mock.patch('deluge.ui.console.main.ConsoleUI'):
@@ -354,8 +381,16 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
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'],
+ sys,
+ 'argv',
+ self.var['sys_arg_cmd']
+ + ['--port']
+ + ['58900']
+ + ['--username']
+ + [username]
+ + ['--password']
+ + [password]
+ + ['status'],
)
fd = StringFileDescriptor(sys.stdout)
self.patch(sys, 'stdout', fd)
@@ -363,10 +398,15 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
yield self.exec_command()
std_output = fd.out.getvalue()
- self.assertTrue(std_output.startswith('Total upload: ') and std_output.endswith(' Moving: 0\n'))
+ self.assertTrue(
+ std_output.startswith('Total upload: ')
+ and std_output.endswith(' Moving: 0\n')
+ )
-class ConsoleScriptEntryWithDaemonTestCase(BaseTestCase, ConsoleUIWithDaemonBaseTestCase):
+class ConsoleScriptEntryWithDaemonTestCase(
+ BaseTestCase, ConsoleUIWithDaemonBaseTestCase
+):
if windows_check():
skip = 'cannot test console ui on windows'
diff --git a/deluge/tests/test_web_api.py b/deluge/tests/test_web_api.py
index 22ec233e9..982a93b1f 100644
--- a/deluge/tests/test_web_api.py
+++ b/deluge/tests/test_web_api.py
@@ -27,7 +27,6 @@ common.disable_new_release_check()
class WebAPITestCase(WebServerTestBase):
-
def test_connect_invalid_host(self):
d = self.deluge_web.web_api.connect('id')
d.addCallback(self.fail)
@@ -73,7 +72,7 @@ class WebAPITestCase(WebServerTestBase):
'login': 'skrot',
'expires': 1460030877.0,
'level': 10,
- },
+ }
}
self.deluge_web.web_api.set_config(config)
web_config = component.get('DelugeWeb').config.config
@@ -98,7 +97,9 @@ class WebAPITestCase(WebServerTestBase):
conn = ['abcdef', '10.0.0.1', 0, 'user123', 'pass123']
self.assertFalse(self.deluge_web.web_api._get_host(conn[0]))
# Add valid host
- result, host_id = self.deluge_web.web_api.add_host(conn[1], conn[2], conn[3], conn[4])
+ result, host_id = self.deluge_web.web_api.add_host(
+ conn[1], conn[2], conn[3], conn[4]
+ )
self.assertEqual(result, True)
conn[0] = host_id
self.assertEqual(self.deluge_web.web_api._get_host(conn[0]), conn[0:4])
@@ -130,7 +131,9 @@ class WebAPITestCase(WebServerTestBase):
self.assertTrue('files_tree' in ret)
def test_get_magnet_info(self):
- ret = self.deluge_web.web_api.get_magnet_info('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN')
+ ret = self.deluge_web.web_api.get_magnet_info(
+ 'magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN'
+ )
self.assertEqual(ret['name'], '953bad769164e8482c7785a21d12166f94b9e14d')
self.assertEqual(ret['info_hash'], '953bad769164e8482c7785a21d12166f94b9e14d')
self.assertTrue('files_tree' in ret)
@@ -139,16 +142,26 @@ class WebAPITestCase(WebServerTestBase):
def test_get_torrent_files(self):
yield self.deluge_web.web_api.connect(self.host_id)
filename = common.get_test_data_file('test.torrent')
- torrents = [{'path': filename, 'options': {'download_location': '/home/deluge/'}}]
+ torrents = [
+ {'path': filename, 'options': {'download_location': '/home/deluge/'}}
+ ]
yield self.deluge_web.web_api.add_torrents(torrents)
- ret = yield self.deluge_web.web_api.get_torrent_files('ab570cdd5a17ea1b61e970bb72047de141bce173')
+ ret = yield self.deluge_web.web_api.get_torrent_files(
+ 'ab570cdd5a17ea1b61e970bb72047de141bce173'
+ )
self.assertEqual(ret['type'], 'dir')
self.assertEqual(
- ret['contents'], {
+ 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,
- },
+ 'priority': 4,
+ 'index': 0,
+ 'offset': 0,
+ 'progress': 0.0,
+ 'path': 'azcvsupdater_2.6.2.jar',
+ 'type': 'file',
+ 'size': 307949,
+ }
},
)
@@ -156,7 +169,8 @@ class WebAPITestCase(WebServerTestBase):
def test_download_torrent_from_url(self):
filename = 'ubuntu-9.04-desktop-i386.iso.torrent'
self.deluge_web.top_level.putChild(
- filename.encode(), File(common.get_test_data_file(filename)))
+ filename.encode(), File(common.get_test_data_file(filename))
+ )
url = 'http://localhost:%d/%s' % (self.webserver_listen_port, filename)
res = yield self.deluge_web.web_api.download_torrent_from_url(url)
self.assertTrue(res.endswith(filename))
@@ -174,10 +188,12 @@ class WebAPITestCase(WebServerTestBase):
d = yield agent.request(
b'POST',
b'http://127.0.0.1:%i/json' % self.webserver_listen_port,
- Headers({
- b'User-Agent': [b'Twisted Web Client Example'],
- b'Content-Type': [b'application/json'],
- }),
+ Headers(
+ {
+ b'User-Agent': [b'Twisted Web Client Example'],
+ b'Content-Type': [b'application/json'],
+ }
+ ),
FileBodyProducer(BytesIO(bad_body)),
)
yield d
diff --git a/deluge/tests/test_webserver.py b/deluge/tests/test_webserver.py
index b2454d2d6..abfac366e 100644
--- a/deluge/tests/test_webserver.py
+++ b/deluge/tests/test_webserver.py
@@ -25,7 +25,6 @@ common.disable_new_release_check()
class WebServerTestCase(WebServerTestBase, WebServerMockBase):
-
@defer.inlineCallbacks
def test_get_torrent_info(self):
@@ -38,7 +37,9 @@ class WebServerTestCase(WebServerTestBase, WebServerMockBase):
# encoded to allow dumping the torrent info to json. Otherwise it will fail with:
# 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
+ input_file = (
+ '{"params": ["%s"], "method": "web.get_torrent_info", "id": 22}' % filename
+ )
headers = {
b'User-Agent': ['Twisted Web Client Example'],
b'Content-Type': ['application/json'],
diff --git a/deluge/tests/twisted/plugins/delugereporter.py b/deluge/tests/twisted/plugins/delugereporter.py
index e0f4fc7d1..340b61cb5 100644
--- a/deluge/tests/twisted/plugins/delugereporter.py
+++ b/deluge/tests/twisted/plugins/delugereporter.py
@@ -19,7 +19,9 @@ from zope.interface import implements
class _Reporter(object):
implements(IPlugin, IReporter)
- def __init__(self, name, module, description, longOpt, shortOpt, klass): # NOQA: N803
+ def __init__( # NOQA: N803
+ self, name, module, description, longOpt, shortOpt, klass
+ ):
self.name = name
self.module = module
self.description = description
@@ -39,7 +41,6 @@ deluge = _Reporter(
class DelugeReporter(TreeReporter):
-
def __init__(self, *args, **kwargs):
os.environ['DELUGE_REPORTER'] = 'true'
TreeReporter.__init__(self, *args, **kwargs)
diff --git a/deluge/transfer.py b/deluge/transfer.py
index c1859eb67..85274d46c 100644
--- a/deluge/transfer.py
+++ b/deluge/transfer.py
@@ -32,6 +32,7 @@ class DelugeTransferProtocol(Protocol, object):
the length of the data to be transfered (payload).
"""
+
def __init__(self):
self._buffer = b'' # TODO: Look into using bytearray instead of byte string.
self._message_length = 0
@@ -78,9 +79,9 @@ class DelugeTransferProtocol(Protocol, object):
self._handle_new_message()
# We have a complete packet
if len(self._buffer) >= self._message_length:
- self._handle_complete_message(self._buffer[:self._message_length])
+ self._handle_complete_message(self._buffer[: self._message_length])
# Remove message data from buffer
- self._buffer = self._buffer[self._message_length:]
+ self._buffer = self._buffer[self._message_length :]
self._message_length = 0
else:
break
@@ -96,7 +97,9 @@ class DelugeTransferProtocol(Protocol, object):
header = self._buffer[:MESSAGE_HEADER_SIZE]
payload_len = header[1:MESSAGE_HEADER_SIZE]
if header[0:1] != b'D':
- raise Exception('Invalid header format. First byte is %d' % ord(header[0:1]))
+ raise Exception(
+ 'Invalid header format. First byte is %d' % ord(header[0:1])
+ )
# Extract the length stored as a signed integer (using 4 bytes)
self._message_length = struct.unpack('!i', payload_len)[0]
if self._message_length < 0:
@@ -105,7 +108,9 @@ class DelugeTransferProtocol(Protocol, object):
self._buffer = self._buffer[MESSAGE_HEADER_SIZE:]
except Exception as ex:
log.warning('Error occurred when parsing message header: %s.', ex)
- log.warning('This version of Deluge cannot communicate with the sender of this data.')
+ log.warning(
+ 'This version of Deluge cannot communicate with the sender of this data.'
+ )
self._message_length = 0
self._buffer = b''
@@ -117,9 +122,15 @@ class DelugeTransferProtocol(Protocol, object):
"""
try:
- self.message_received(rencode.loads(zlib.decompress(data), decode_utf8=True))
+ self.message_received(
+ rencode.loads(zlib.decompress(data), decode_utf8=True)
+ )
except Exception as ex:
- log.warning('Failed to decompress (%d bytes) and load serialized data with rencode: %s', len(data), ex)
+ log.warning(
+ 'Failed to decompress (%d bytes) and load serialized data with rencode: %s',
+ len(data),
+ ex,
+ )
def get_bytes_recv(self):
"""
diff --git a/deluge/ui/Win32IconImagePlugin.py b/deluge/ui/Win32IconImagePlugin.py
index caa653590..3d720e87b 100644
--- a/deluge/ui/Win32IconImagePlugin.py
+++ b/deluge/ui/Win32IconImagePlugin.py
@@ -82,20 +82,34 @@ class Win32IcoFile(object):
self.nb_items = header[2]
- dir_fields = ('width', 'height', 'nb_color', 'reserved', 'planes', 'bpp', 'size', 'offset')
+ dir_fields = (
+ 'width',
+ 'height',
+ 'nb_color',
+ 'reserved',
+ 'planes',
+ 'bpp',
+ 'size',
+ 'offset',
+ )
for i in range(self.nb_items):
directory = list(struct.unpack('<4B2H2I', buf.read(16)))
for j in range(3):
if not directory[j]:
directory[j] = 256
icon_header = dict(zip(dir_fields, directory))
- icon_header['color_depth'] = (icon_header['bpp'] or (icon_header['nb_color'] == 16 and 4))
+ icon_header['color_depth'] = icon_header['bpp'] or (
+ icon_header['nb_color'] == 16 and 4
+ )
icon_header['dim'] = (icon_header['width'], icon_header['height'])
self.entry.append(icon_header)
# end for (read headers)
# order by size and color depth
- self.entry.sort(lambda x, y: cmp(x['width'], y['width']) or cmp(x['color_depth'], y['color_depth']))
+ self.entry.sort(
+ lambda x, y: cmp(x['width'], y['width'])
+ or cmp(x['color_depth'], y['color_depth'])
+ )
self.entry.reverse()
def sizes(self):
@@ -167,11 +181,11 @@ class Win32IcoFile(object):
# convert to an 8bpp grayscale image
mask = PIL.Image.frombuffer(
- 'L', # 8bpp
- im.size, # (w, h)
- alpha_bytes, # source chars
- 'raw', # raw decoder
- ('L', 0, -1), # 8bpp inverted, unpadded, reversed
+ 'L', # 8bpp
+ im.size, # (w, h)
+ alpha_bytes, # source chars
+ 'raw', # raw decoder
+ ('L', 0, -1), # 8bpp inverted, unpadded, reversed
)
# apply mask image as alpha channel
@@ -187,17 +201,23 @@ class Win32IcoFile(object):
w += 32 - (im.size[0] % 32)
# the total mask data is padded row size * height / bits per char
total_bytes = (w * im.size[1]) // 8
- log.debug('tot=%d, off=%d, w=%d, size=%d', len(data), and_mask_offset, w, total_bytes)
+ log.debug(
+ 'tot=%d, off=%d, w=%d, size=%d',
+ len(data),
+ and_mask_offset,
+ w,
+ total_bytes,
+ )
self.buf.seek(and_mask_offset)
mask_data = self.buf.read(total_bytes)
# convert raw data to image
mask = PIL.Image.frombuffer(
- '1', # 1 bpp
- im.size, # (w, h)
- mask_data, # source chars
- 'raw', # raw decoder
+ '1', # 1 bpp
+ im.size, # (w, h)
+ mask_data, # source chars
+ 'raw', # raw decoder
('1;I', w // 8, -1), # 1bpp inverted, padded, reversed
)
@@ -210,14 +230,19 @@ class Win32IcoFile(object):
# end if (png)/else(bmp)
return im
+
# end frame
def __repr__(self):
s = 'Microsoft Icon: %d images (max %dx%d %dbpp)' % (
- len(self.entry), self.entry[0]['width'], self.entry[0]['height'],
+ len(self.entry),
+ self.entry[0]['width'],
+ self.entry[0]['height'],
self.entry[0]['bpp'],
)
return s
+
+
# end Win32IcoFile
@@ -250,6 +275,8 @@ class Win32IconImageFile(PIL.ImageFile.ImageFile): # pylint: disable=abstract-m
self.im = im.im
self.mode = im.mode
self.size = im.size
+
+
# end class Win32IconImageFile
@@ -258,6 +285,8 @@ def _accept(prefix):
Quick file test helper for Image.open()
"""
return prefix[:4] == _MAGIC
+
+
# end _accept
diff --git a/deluge/ui/baseargparser.py b/deluge/ui/baseargparser.py
index 6bedc8093..6024e99d5 100644
--- a/deluge/ui/baseargparser.py
+++ b/deluge/ui/baseargparser.py
@@ -90,6 +90,7 @@ def get_version():
version_str = '%s\n' % (common.get_version())
try:
from deluge._libtorrent import LT_VERSION
+
version_str += 'libtorrent: %s\n' % LT_VERSION
except ImportError:
pass
@@ -141,7 +142,6 @@ class DelugeTextHelpFormatter(argparse.RawDescriptionHelpFormatter):
class HelpAction(argparse._HelpAction):
-
def __call__(self, parser, namespace, values, option_string=None):
if hasattr(parser, 'subparser'):
subparser = getattr(parser, 'subparser')
@@ -152,10 +152,11 @@ class HelpAction(argparse._HelpAction):
class BaseArgParser(argparse.ArgumentParser):
-
def __init__(self, *args, **kwargs):
if 'formatter_class' not in kwargs:
- kwargs['formatter_class'] = lambda prog: DelugeTextHelpFormatter(prog, max_help_position=33, width=90)
+ kwargs['formatter_class'] = lambda prog: DelugeTextHelpFormatter(
+ prog, max_help_position=33, width=90
+ )
kwargs['add_help'] = kwargs.get('add_help', False)
common_help = kwargs.pop('common_help', True)
@@ -171,45 +172,64 @@ class BaseArgParser(argparse.ArgumentParser):
self.group = self.add_argument_group(_('Common Options'))
if common_help:
self.group.add_argument(
- '-h', '--help', action=HelpAction,
- help=_('Print this help message'),
+ '-h', '--help', action=HelpAction, help=_('Print this help message')
)
self.group.add_argument(
- '-V', '--version', action='version', version='%(prog)s ' + get_version(),
+ '-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(),
+ '-v',
+ action='version',
+ version='%(prog)s ' + get_version(),
help=argparse.SUPPRESS,
) # Deprecated arg
self.group.add_argument(
- '-c', '--config', metavar='<config>',
+ '-c',
+ '--config',
+ metavar='<config>',
help=_('Set the config directory path'),
)
self.group.add_argument(
- '-l', '--logfile', metavar='<logfile>',
+ '-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>',
+ '-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>',
+ '--logrotate',
+ nargs='?',
+ const='2M',
+ metavar='<max-size>',
help=_(
'Enable logfile rotation, with optional maximum logfile size, '
- 'default: %(const)s (Logfile rotation count is 5)',
+ 'default: %(const)s (Logfile rotation count is 5)'
),
)
self.group.add_argument(
- '-q', '--quiet', action='store_true',
+ '-q',
+ '--quiet',
+ action='store_true',
help=_('Quieten logging output (Same as `--loglevel none`)'),
)
self.group.add_argument(
- '--profile', metavar='<profile-file>', nargs='?', default=False,
+ '--profile',
+ metavar='<profile-file>',
+ nargs='?',
+ default=False,
help=_(
'Profile %(prog)s with cProfile. Outputs to stdout '
- 'unless a filename is specified',
+ 'unless a filename is specified'
),
)
@@ -274,8 +294,11 @@ class BaseArgParser(argparse.ArgumentParser):
# Setup the logger
deluge.log.setup_logger(
- level=options.loglevel, filename=options.logfile, filemode=logfile_mode,
- logrotate=logrotate, output_stream=self.log_stream,
+ level=options.loglevel,
+ filename=options.logfile,
+ filemode=logfile_mode,
+ logrotate=logrotate,
+ output_stream=self.log_stream,
)
if options.config:
@@ -309,11 +332,13 @@ class BaseArgParser(argparse.ArgumentParser):
if options.user:
if not options.user.isdigit():
import pwd
+
options.user = pwd.getpwnam(options.user)[2]
os.setuid(options.user)
if options.group:
if not options.group.isdigit():
import grp
+
options.group = grp.getgrnam(options.group)[2]
os.setuid(options.group)
@@ -325,23 +350,38 @@ 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',
+ '-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',
+ '-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',
+ '-f',
+ '--fork',
+ dest='donotdaemonize',
+ action='store_false',
help=argparse.SUPPRESS,
) # Deprecated arg
self.group.add_argument(
- '-U', '--user', metavar='<user>', action='store',
+ '-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',
+ '-g',
+ '--group',
+ metavar='<group>',
+ action='store',
help=_('Change to this group on startup (Requires root)'),
)
diff --git a/deluge/ui/client.py b/deluge/ui/client.py
index 64db4ce06..7f37c7b1c 100644
--- a/deluge/ui/client.py
+++ b/deluge/ui/client.py
@@ -67,14 +67,20 @@ class DelugeRPCRequest(object):
:returns: a properly formated RPCRequest
"""
- if self.request_id is None or self.method is None or self.args is None or self.kwargs is None:
- raise TypeError('You must set the properties of this object before calling format_message!')
+ if (
+ self.request_id is None
+ or self.method is None
+ or self.args is None
+ or self.kwargs is None
+ ):
+ raise TypeError(
+ 'You must set the properties of this object before calling format_message!'
+ )
return (self.request_id, self.method, self.args, self.kwargs)
class DelugeRPCProtocol(DelugeTransferProtocol):
-
def connectionMade(self): # NOQA: N802
self.__rpc_requests = {}
# Set the protocol in the daemon so it can send data
@@ -99,8 +105,8 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
return
if len(request) < 3:
log.debug(
- 'Received invalid message: number of items in '
- 'response is %s', len(request),
+ 'Received invalid message: number of items in ' 'response is %s',
+ len(request),
)
return
@@ -133,7 +139,9 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
exception_cls = getattr(error, request[2])
exception = exception_cls(*request[3], **request[4])
except TypeError:
- log.warning('Received invalid RPC_ERROR (Old daemon?): %s', request[2])
+ log.warning(
+ 'Received invalid RPC_ERROR (Old daemon?): %s', request[2]
+ )
return
# Ideally we would chain the deferreds instead of instance
@@ -165,9 +173,11 @@ 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(),
+ request[2],
+ traceback.format_exc(),
)
d.errback(exception)
del self.__rpc_requests[request_id]
@@ -199,29 +209,33 @@ 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,
+ 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,
+ connector.host,
+ connector.port,
+ reason.value,
)
self.daemon.host = None
self.daemon.port = None
self.daemon.username = None
self.daemon.connected = False
- if self.daemon.disconnect_deferred and not self.daemon.disconnect_deferred.called:
+ if (
+ self.daemon.disconnect_deferred
+ and not self.daemon.disconnect_deferred.called
+ ):
self.daemon.disconnect_deferred.callback(reason.value)
self.daemon.disconnect_deferred = None
@@ -273,9 +287,7 @@ class DaemonSSLProxy(DaemonProxy):
self.host = host
self.port = port
self.__connector = reactor.connectSSL(
- self.host, self.port,
- self.__factory,
- ssl.ClientContextFactory(),
+ self.host, self.port, self.__factory, ssl.ClientContextFactory()
)
self.connect_deferred = defer.Deferred()
self.daemon_info_deferred = defer.Deferred()
@@ -370,7 +382,10 @@ class DaemonSSLProxy(DaemonProxy):
:type handler: function
"""
- if event in self.__factory.event_handlers and handler in self.__factory.event_handlers[event]:
+ if (
+ event in self.__factory.event_handlers
+ and handler in self.__factory.event_handlers[event]
+ ):
self.__factory.event_handlers[event].remove(handler)
def __on_connect(self, result):
@@ -397,7 +412,9 @@ class DaemonSSLProxy(DaemonProxy):
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],
+ self.__on_login,
+ self.__on_login_fail,
+ callbackArgs=[username, login_deferred],
errbackArgs=[login_deferred],
)
return login_deferred
@@ -410,7 +427,7 @@ 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)
@@ -442,6 +459,7 @@ class DaemonStandaloneProxy(DaemonProxy):
if event_handlers is None:
event_handlers = {}
from deluge.core import daemon
+
self.__daemon = daemon.Daemon(standalone=True)
self.__daemon.start()
log.debug('daemon created!')
@@ -454,6 +472,7 @@ class DaemonStandaloneProxy(DaemonProxy):
AUTH_LEVELS_MAPPING,
AUTH_LEVELS_MAPPING_REVERSE,
)
+
self.username = 'localclient'
self.authentication_level = AUTH_LEVEL_ADMIN
self.auth_levels_mapping = AUTH_LEVELS_MAPPING
@@ -478,9 +497,7 @@ class DaemonStandaloneProxy(DaemonProxy):
log.exception(ex)
return defer.fail(ex)
else:
- return defer.maybeDeferred(
- m, *copy.deepcopy(args), **copy.deepcopy(kwargs)
- )
+ return defer.maybeDeferred(m, *copy.deepcopy(args), **copy.deepcopy(kwargs))
def register_event_handler(self, event, handler):
"""
@@ -513,6 +530,7 @@ class DottedObject(object):
"""
This is used for dotted name calls to client
"""
+
def __init__(self, daemon, method):
self.daemon = daemon
self.base = method
@@ -528,6 +546,7 @@ class RemoteMethod(DottedObject):
"""
This is used when something like 'client.core.get_something()' is attempted.
"""
+
def __call__(self, *args, **kwargs):
return self.daemon.call(self.base, *args, **kwargs)
@@ -537,8 +556,7 @@ class Client(object):
This class is used to connect to a daemon process and issue RPC requests.
"""
- __event_handlers = {
- }
+ __event_handlers = {}
def __init__(self):
self._daemon_proxy = None
@@ -546,7 +564,11 @@ class Client(object):
self.__started_standalone = False
def connect(
- self, host='127.0.0.1', port=58846, username='', password='',
+ self,
+ host='127.0.0.1',
+ port=58846,
+ username='',
+ password='',
skip_authentication=False,
):
"""
@@ -652,12 +674,13 @@ class Client(object):
subprocess.Popen(['deluged', '--port=%s' % port, '--config=%s' % config])
except OSError as ex:
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.',
- ),
+ 'the deluged package is installed, or added to your PATH.'
+ )
)
else:
log.exception(ex)
@@ -675,8 +698,11 @@ class Client(object):
:returns: bool, True if connected to a localhost
"""
- if (self._daemon_proxy and self._daemon_proxy.host in ('127.0.0.1', 'localhost') or
- isinstance(self._daemon_proxy, DaemonStandaloneProxy)):
+ if (
+ self._daemon_proxy
+ and self._daemon_proxy.host in ('127.0.0.1', 'localhost')
+ or isinstance(self._daemon_proxy, DaemonStandaloneProxy)
+ ):
return True
return False
@@ -710,7 +736,11 @@ class Client(object):
:returns: a tuple of (host, port, username) or None if not connected
"""
if self.connected():
- return (self._daemon_proxy.host, self._daemon_proxy.port, self._daemon_proxy.username)
+ return (
+ self._daemon_proxy.host,
+ self._daemon_proxy.port,
+ self._daemon_proxy.username,
+ )
return None
diff --git a/deluge/ui/common.py b/deluge/ui/common.py
index b9866d21c..91b56ea44 100644
--- a/deluge/ui/common.py
+++ b/deluge/ui/common.py
@@ -45,96 +45,75 @@ STATE_TRANSLATION = {
}
TORRENT_DATA_FIELD = {
- 'queue':
- {'name': '#', 'status': ['queue']},
- 'name':
- {'name': _('Name'), 'status': ['state', 'name']},
- 'progress_state':
- {'name': _('Progress'), 'status': ['progress', 'state']},
- 'state':
- {'name': _('State'), 'status': ['state']},
- 'progress':
- {'name': _('Progress'), 'status': ['progress']},
- 'size':
- {'name': _('Size'), 'status': ['total_wanted']},
- 'downloaded':
- {'name': _('Downloaded'), 'status': ['all_time_download']},
- 'uploaded':
- {'name': _('Uploaded'), 'status': ['total_uploaded']},
- 'remaining':
- {'name': _('Remaining'), 'status': ['total_remaining']},
- 'ratio':
- {'name': _('Ratio'), 'status': ['ratio']},
- 'download_speed':
- {'name': _('Down Speed'), 'status': ['download_payload_rate']},
- 'upload_speed':
- {'name': _('Up Speed'), 'status': ['upload_payload_rate']},
- 'max_download_speed':
- {'name': _('Down Limit'), 'status': ['max_download_speed']},
- 'max_upload_speed':
- {'name': _('Up Limit'), 'status': ['max_upload_speed']},
- 'max_connections':
- {'name': _('Max Connections'), 'status': ['max_connections']},
- 'max_upload_slots':
- {'name': _('Max Upload Slots'), 'status': ['max_upload_slots']},
- 'peers':
- {'name': _('Peers'), 'status': ['num_peers', 'total_peers']},
- 'seeds':
- {'name': _('Seeds'), 'status': ['num_seeds', 'total_seeds']},
- 'avail':
- {'name': _('Avail'), 'status': ['distributed_copies']},
- 'seeds_peers_ratio':
- {'name': _('Seeds:Peers'), 'status': ['seeds_peers_ratio']},
- 'time_added':
- {'name': _('Added'), 'status': ['time_added']},
- 'tracker':
- {'name': _('Tracker'), 'status': ['tracker_host']},
- 'download_location':
- {'name': _('Download Folder'), 'status': ['download_location']},
- 'seeding_time':
- {'name': _('Seeding Time'), 'status': ['seeding_time']},
- 'active_time':
- {'name': _('Active Time'), 'status': ['active_time']},
- 'time_since_transfer':
- {'name': _('Last Activity'), 'status': ['time_since_transfer']},
- 'finished_time':
- {'name': _('Finished Time'), 'status': ['finished_time']},
- 'last_seen_complete':
- {'name': _('Complete Seen'), 'status': ['last_seen_complete']},
- 'completed_time':
- {'name': _('Completed'), 'status': ['completed_time']},
- 'eta':
- {'name': _('ETA'), 'status': ['eta']},
- 'shared':
- {'name': _('Shared'), 'status': ['shared']},
- 'prioritize_first_last':
- {'name': _('Prioritize First/Last'), 'status': ['prioritize_first_last']},
- 'sequential_download':
- {'name': _('Sequential Download'), 'status': ['sequential_download']},
- 'is_auto_managed':
- {'name': _('Auto Managed'), 'status': ['is_auto_managed']},
- 'auto_managed':
- {'name': _('Auto Managed'), 'status': ['auto_managed']},
- 'stop_at_ratio':
- {'name': _('Stop At Ratio'), 'status': ['stop_at_ratio']},
- 'stop_ratio':
- {'name': _('Stop Ratio'), 'status': ['stop_ratio']},
- 'remove_at_ratio':
- {'name': _('Remove At Ratio'), 'status': ['remove_at_ratio']},
- 'move_completed':
- {'name': _('Move On Completed'), 'status': ['move_completed']},
- 'move_completed_path':
- {'name': _('Move Completed Path'), 'status': ['move_completed_path']},
- 'move_on_completed':
- {'name': _('Move On Completed'), 'status': ['move_on_completed']},
- 'move_on_completed_path':
- {'name': _('Move On Completed Path'), 'status': ['move_on_completed_path']},
- 'owner':
- {'name': _('Owner'), 'status': ['owner']},
- 'pieces':
- {'name': _('Pieces'), 'status': ['num_pieces', 'piece_length']},
- 'seed_rank':
- {'name': _('Seed Rank'), 'status': ['seed_rank']},
+ 'queue': {'name': '#', 'status': ['queue']},
+ 'name': {'name': _('Name'), 'status': ['state', 'name']},
+ 'progress_state': {'name': _('Progress'), 'status': ['progress', 'state']},
+ 'state': {'name': _('State'), 'status': ['state']},
+ 'progress': {'name': _('Progress'), 'status': ['progress']},
+ 'size': {'name': _('Size'), 'status': ['total_wanted']},
+ 'downloaded': {'name': _('Downloaded'), 'status': ['all_time_download']},
+ 'uploaded': {'name': _('Uploaded'), 'status': ['total_uploaded']},
+ 'remaining': {'name': _('Remaining'), 'status': ['total_remaining']},
+ 'ratio': {'name': _('Ratio'), 'status': ['ratio']},
+ 'download_speed': {'name': _('Down Speed'), 'status': ['download_payload_rate']},
+ 'upload_speed': {'name': _('Up Speed'), 'status': ['upload_payload_rate']},
+ 'max_download_speed': {'name': _('Down Limit'), 'status': ['max_download_speed']},
+ 'max_upload_speed': {'name': _('Up Limit'), 'status': ['max_upload_speed']},
+ 'max_connections': {'name': _('Max Connections'), 'status': ['max_connections']},
+ 'max_upload_slots': {'name': _('Max Upload Slots'), 'status': ['max_upload_slots']},
+ 'peers': {'name': _('Peers'), 'status': ['num_peers', 'total_peers']},
+ 'seeds': {'name': _('Seeds'), 'status': ['num_seeds', 'total_seeds']},
+ 'avail': {'name': _('Avail'), 'status': ['distributed_copies']},
+ 'seeds_peers_ratio': {'name': _('Seeds:Peers'), 'status': ['seeds_peers_ratio']},
+ 'time_added': {'name': _('Added'), 'status': ['time_added']},
+ 'tracker': {'name': _('Tracker'), 'status': ['tracker_host']},
+ 'download_location': {
+ 'name': _('Download Folder'),
+ 'status': ['download_location'],
+ },
+ 'seeding_time': {'name': _('Seeding Time'), 'status': ['seeding_time']},
+ 'active_time': {'name': _('Active Time'), 'status': ['active_time']},
+ 'time_since_transfer': {
+ 'name': _('Last Activity'),
+ 'status': ['time_since_transfer'],
+ },
+ 'finished_time': {'name': _('Finished Time'), 'status': ['finished_time']},
+ 'last_seen_complete': {
+ 'name': _('Complete Seen'),
+ 'status': ['last_seen_complete'],
+ },
+ 'completed_time': {'name': _('Completed'), 'status': ['completed_time']},
+ 'eta': {'name': _('ETA'), 'status': ['eta']},
+ 'shared': {'name': _('Shared'), 'status': ['shared']},
+ 'prioritize_first_last': {
+ 'name': _('Prioritize First/Last'),
+ 'status': ['prioritize_first_last'],
+ },
+ 'sequential_download': {
+ 'name': _('Sequential Download'),
+ 'status': ['sequential_download'],
+ },
+ 'is_auto_managed': {'name': _('Auto Managed'), 'status': ['is_auto_managed']},
+ 'auto_managed': {'name': _('Auto Managed'), 'status': ['auto_managed']},
+ 'stop_at_ratio': {'name': _('Stop At Ratio'), 'status': ['stop_at_ratio']},
+ 'stop_ratio': {'name': _('Stop Ratio'), 'status': ['stop_ratio']},
+ 'remove_at_ratio': {'name': _('Remove At Ratio'), 'status': ['remove_at_ratio']},
+ 'move_completed': {'name': _('Move On Completed'), 'status': ['move_completed']},
+ 'move_completed_path': {
+ 'name': _('Move Completed Path'),
+ 'status': ['move_completed_path'],
+ },
+ 'move_on_completed': {
+ 'name': _('Move On Completed'),
+ 'status': ['move_on_completed'],
+ },
+ 'move_on_completed_path': {
+ 'name': _('Move On Completed Path'),
+ 'status': ['move_on_completed_path'],
+ },
+ 'owner': {'name': _('Owner'), 'status': ['owner']},
+ 'pieces': {'name': _('Pieces'), 'status': ['num_pieces', 'piece_length']},
+ 'seed_rank': {'name': _('Seed Rank'), 'status': ['seed_rank']},
}
TRACKER_STATUS_TRANSLATION = [
@@ -176,8 +155,14 @@ del _
# The keys from session statistics for cache status.
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.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',
]
@@ -192,6 +177,7 @@ class TorrentInfo(object):
metadata (bytes, optional): A bencoded metadata info_dict.
"""
+
def __init__(self, filename='', filetree=1, metainfo=None, metadata=None):
# Get the torrent metainfo from the torrent file
if metadata:
@@ -264,6 +250,7 @@ class TorrentInfo(object):
dirname = os.path.dirname(dirname)
if filetree == 2:
+
def walk(path, item):
if item['type'] == 'dir':
item.update(dirs[path])
@@ -274,6 +261,7 @@ class TorrentInfo(object):
file_tree = FileTree2(list(paths))
file_tree.walk(walk)
else:
+
def walk(path, item):
if isinstance(item, dict):
return item
@@ -291,13 +279,11 @@ class TorrentInfo(object):
'index': 0,
'length': info_dict[b'length'],
'download': True,
- },
- },
+ }
+ }
}
else:
- self._files_tree = {
- self._name: (0, info_dict[b'length'], True),
- }
+ self._files_tree = {self._name: (0, info_dict[b'length'], True)}
self._files = []
if b'files' in info_dict:
@@ -306,17 +292,13 @@ class TorrentInfo(object):
prefix = self._name
for f in info_dict[b'files']:
- self._files.append({
- 'path': f[b'path'],
- 'size': f[b'length'],
- 'download': True,
- })
+ self._files.append(
+ {'path': f[b'path'], 'size': f[b'length'], 'download': True}
+ )
else:
- self._files.append({
- 'path': self._name,
- 'size': info_dict[b'length'],
- 'download': True,
- })
+ self._files.append(
+ {'path': self._name, 'size': info_dict[b'length'], 'download': True}
+ )
def as_dict(self, *keys):
"""The torrent info as a dictionary, filtered by keys.
@@ -414,10 +396,7 @@ class FileTree2(object):
directory, path = path.split('/', 1)
child = parent['contents'].get(directory)
if child is None:
- parent['contents'][directory] = {
- 'type': 'dir',
- 'contents': {},
- }
+ parent['contents'][directory] = {'type': 'dir', 'contents': {}}
parent = parent['contents'][directory]
return parent, path
@@ -425,15 +404,10 @@ class FileTree2(object):
if path[-1] == '/':
path = path[:-1]
parent, path = get_parent(path)
- parent['contents'][path] = {
- 'type': 'dir',
- 'contents': {},
- }
+ parent['contents'][path] = {'type': 'dir', 'contents': {}}
else:
parent, path = get_parent(path)
- parent['contents'][path] = {
- 'type': 'file',
- }
+ parent['contents'][path] = {'type': 'file'}
def get_tree(self):
"""
@@ -454,18 +428,22 @@ class FileTree2(object):
and `dict` for a directory.
:type callback: function
"""
+
def walk(directory, parent_path):
for path in list(directory['contents']):
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]
+ directory['contents'][path] = (
+ callback(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]
+ directory['contents'][path] = (
+ callback(full_path, directory['contents'][path])
+ or directory['contents'][path]
+ )
+
walk(self.tree, '')
def __str__(self):
@@ -476,6 +454,7 @@ class FileTree2(object):
path = os.path.basename(path)
path = path + '/' if item['type'] == 'dir' else path
lines.append(' ' * depth + path)
+
self.walk(write)
return '\n'.join(lines)
@@ -517,10 +496,12 @@ class FileTree(object):
:returns: the file tree.
:rtype: dictionary
"""
+
def to_tuple(path, item):
if isinstance(item, dict):
return item
return tuple(item)
+
self.walk(to_tuple)
return self.tree
@@ -534,14 +515,20 @@ class FileTree(object):
and `dict` for a directory.
:type callback: function
"""
+
def walk(directory, parent_path):
for path in list(directory):
full_path = os.path.join(parent_path, path)
if isinstance(directory[path], dict):
- directory[path] = callback(full_path, directory[path]) or directory[path]
+ directory[path] = (
+ callback(full_path, directory[path]) or directory[path]
+ )
walk(directory[path], full_path)
else:
- directory[path] = callback(full_path, directory[path]) or directory[path]
+ directory[path] = (
+ callback(full_path, directory[path]) or directory[path]
+ )
+
walk(self.tree, '')
def __str__(self):
@@ -552,5 +539,6 @@ class FileTree(object):
path = os.path.basename(path)
path = isinstance(item, dict) and path + '/' or path
lines.append(' ' * depth + path)
+
self.walk(write)
return '\n'.join(lines)
diff --git a/deluge/ui/console/cmdline/command.py b/deluge/ui/console/cmdline/command.py
index 0b59aca7b..2ff32dff9 100644
--- a/deluge/ui/console/cmdline/command.py
+++ b/deluge/ui/console/cmdline/command.py
@@ -24,7 +24,6 @@ log = logging.getLogger(__name__)
class Commander(object):
-
def __init__(self, cmds, interactive=False):
self._commands = cmds
self.interactive = interactive
@@ -85,6 +84,7 @@ class Commander(object):
self.write(parser.format_help())
else:
parser._print_help(f)
+
parser.print_help = print_help
# Only these commands can be run when not connected to a daemon
@@ -95,7 +95,9 @@ class Commander(object):
not_connected_cmds.extend(aliases)
if not client.connected() and cmd not in not_connected_cmds:
- self.write('{!error!}Not connected to a daemon, please use the connect command first.')
+ self.write(
+ '{!error!}Not connected to a daemon, please use the connect command first.'
+ )
return
try:
@@ -104,10 +106,12 @@ class Commander(object):
except TypeError as ex:
self.write('{!error!}Error parsing options: %s' % ex)
import traceback
+
self.write('%s' % traceback.format_exc())
return
except OptionParserError as ex:
import traceback
+
log.warning('Error parsing command "%s": %s', args, ex)
self.write('{!error!} %s' % ex)
parser.print_help()
@@ -133,6 +137,7 @@ class Commander(object):
self.write('{!error!} %s' % ex)
log.exception(ex)
import traceback
+
self.write('%s' % traceback.format_exc())
return defer.succeed(True)
else:
@@ -174,7 +179,11 @@ class BaseCommand(object):
return result
def create_parser(self):
- opts = {'prog': self.name_with_alias, 'description': self.__doc__, 'epilog': self.epilog}
+ opts = {
+ 'prog': self.name_with_alias,
+ 'description': self.__doc__,
+ 'epilog': self.epilog,
+ }
if self.usage:
opts['usage'] = self.usage
parser = OptionParser(**opts)
@@ -184,7 +193,11 @@ class BaseCommand(object):
return parser
def add_subparser(self, subparsers):
- opts = {'prog': self.name_with_alias, 'help': self.__doc__, 'description': self.__doc__}
+ opts = {
+ 'prog': self.name_with_alias,
+ 'help': self.__doc__,
+ 'description': self.__doc__,
+ }
if self.usage:
opts['usage'] = self.usage
diff --git a/deluge/ui/console/cmdline/commands/add.py b/deluge/ui/console/cmdline/commands/add.py
index df0da2db3..e2baf2740 100644
--- a/deluge/ui/console/cmdline/commands/add.py
+++ b/deluge/ui/console/cmdline/commands/add.py
@@ -34,9 +34,13 @@ class Command(BaseCommand):
"""Add torrents"""
def add_arguments(self, parser):
- parser.add_argument('-p', '--path', dest='path', help=_('download folder for torrent'))
parser.add_argument(
- 'torrents', metavar='<torrent>', nargs='+',
+ '-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'),
)
@@ -45,7 +49,9 @@ class Command(BaseCommand):
t_options = {}
if options.path:
- t_options['download_location'] = os.path.abspath(os.path.expanduser(options.path))
+ t_options['download_location'] = os.path.abspath(
+ os.path.expanduser(options.path)
+ )
def on_success(result):
if not result:
@@ -62,15 +68,23 @@ class Command(BaseCommand):
if not torrent.strip():
continue
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,
- ))
+ 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)
+ )
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,
- ))
+ 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)
+ )
else:
# Just a file
if urlparse(torrent).scheme == 'file':
@@ -87,12 +101,14 @@ class Command(BaseCommand):
with open(path, 'rb') as _file:
filedump = b64encode(_file.read())
deferreds.append(
- client.core.add_torrent_file_async(
- filename, filedump, t_options,
- ).addCallback(on_success).addErrback(on_fail),
+ client.core.add_torrent_file_async(filename, filedump, t_options)
+ .addCallback(on_success)
+ .addErrback(on_fail)
)
return defer.DeferredList(deferreds)
def complete(self, line):
- return component.get('ConsoleUI').tab_complete_path(line, ext='.torrent', sort='date')
+ return component.get('ConsoleUI').tab_complete_path(
+ line, ext='.torrent', sort='date'
+ )
diff --git a/deluge/ui/console/cmdline/commands/cache.py b/deluge/ui/console/cmdline/commands/cache.py
index cbe61bace..e427f085f 100644
--- a/deluge/ui/console/cmdline/commands/cache.py
+++ b/deluge/ui/console/cmdline/commands/cache.py
@@ -26,4 +26,6 @@ class Command(BaseCommand):
for key, value in sorted(status.items()):
self.console.write('{!info!}%s: {!input!}%s' % (key, value))
- return client.core.get_session_status(DISK_CACHE_KEYS).addCallback(on_cache_status)
+ return client.core.get_session_status(DISK_CACHE_KEYS).addCallback(
+ on_cache_status
+ )
diff --git a/deluge/ui/console/cmdline/commands/config.py b/deluge/ui/console/cmdline/commands/config.py
index d9132d739..1cbccba88 100644
--- a/deluge/ui/console/cmdline/commands/config.py
+++ b/deluge/ui/console/cmdline/commands/config.py
@@ -80,10 +80,23 @@ class Command(BaseCommand):
def add_arguments(self, parser):
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'))
+ 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')
+ )
get_group = parser.add_argument_group('getting values')
- get_group.add_argument('keys', metavar='<keys>', nargs='*', help=_('one or more keys separated by space'))
+ get_group.add_argument(
+ 'keys',
+ metavar='<keys>',
+ nargs='*',
+ help=_('one or more keys separated by space'),
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
@@ -109,6 +122,7 @@ class Command(BaseCommand):
# We need to format dicts for printing
if isinstance(value, dict):
import pprint
+
value = pprint.pformat(value, 2, 80)
new_value = []
for line in value.splitlines():
@@ -139,7 +153,9 @@ class Command(BaseCommand):
try:
val = type(config[key])(val)
except TypeError:
- self.config.write('{!error!}Configuration value provided has incorrect type.')
+ self.config.write(
+ '{!error!}Configuration value provided has incorrect type.'
+ )
return
def on_set_config(result):
diff --git a/deluge/ui/console/cmdline/commands/connect.py b/deluge/ui/console/cmdline/commands/connect.py
index 356db6d9f..6588f7a04 100644
--- a/deluge/ui/console/cmdline/commands/connect.py
+++ b/deluge/ui/console/cmdline/commands/connect.py
@@ -26,12 +26,20 @@ class Command(BaseCommand):
usage = _('Usage: connect <host[:port]> [<username>] [<password>]')
def add_arguments(self, parser):
- parser.add_argument('host', help=_('Daemon host and port'), metavar='<host[:port]>')
- parser.add_argument('username', help=_('Username'), metavar='<username>', nargs='?', default='')
- parser.add_argument('password', help=_('Password'), metavar='<password>', nargs='?', default='')
+ parser.add_argument(
+ 'host', help=_('Daemon host and port'), metavar='<host[:port]>'
+ )
+ parser.add_argument(
+ 'username', help=_('Username'), metavar='<username>', nargs='?', default=''
+ )
+ parser.add_argument(
+ 'password', help=_('Password'), metavar='<password>', nargs='?', default=''
+ )
def add_parser(self, subparsers):
- parser = subparsers.add_parser(self.name, help=self.__doc__, description=self.__doc__, prog='connect')
+ parser = subparsers.add_parser(
+ self.name, help=self.__doc__, description=self.__doc__, prog='connect'
+ )
self.add_arguments(parser)
def handle(self, options):
@@ -57,7 +65,10 @@ class Command(BaseCommand):
msg = result.value.exception_msg
except AttributeError:
msg = result.value.message
- self.console.write('{!error!}Failed to connect to %s:%s with reason: %s' % (host, port, msg))
+ self.console.write(
+ '{!error!}Failed to connect to %s:%s with reason: %s'
+ % (host, port, msg)
+ )
return result
d.addCallbacks(on_connect, on_connect_fail)
@@ -69,6 +80,7 @@ class Command(BaseCommand):
if self.console.statusbars:
self.console.statusbars.update_statusbars()
return do_connect()
+
return client.disconnect().addCallback(on_disconnect)
else:
return do_connect()
diff --git a/deluge/ui/console/cmdline/commands/debug.py b/deluge/ui/console/cmdline/commands/debug.py
index f65d172b5..3ca06ed15 100644
--- a/deluge/ui/console/cmdline/commands/debug.py
+++ b/deluge/ui/console/cmdline/commands/debug.py
@@ -22,7 +22,9 @@ class Command(BaseCommand):
"""Enable and disable debugging"""
def add_arguments(self, parser):
- parser.add_argument('state', metavar='<on|off>', choices=['on', 'off'], help=_('The new state'))
+ parser.add_argument(
+ 'state', metavar='<on|off>', choices=['on', 'off'], help=_('The new state')
+ )
def handle(self, options):
if options.state == 'on':
diff --git a/deluge/ui/console/cmdline/commands/gui.py b/deluge/ui/console/cmdline/commands/gui.py
index 88c8ca5a6..10e4c499b 100644
--- a/deluge/ui/console/cmdline/commands/gui.py
+++ b/deluge/ui/console/cmdline/commands/gui.py
@@ -20,6 +20,7 @@ log = logging.getLogger(__name__)
class Command(BaseCommand):
"""Enable interactive mode"""
+
interactive_only = True
def handle(self, options):
diff --git a/deluge/ui/console/cmdline/commands/halt.py b/deluge/ui/console/cmdline/commands/halt.py
index ef22873e9..635595898 100644
--- a/deluge/ui/console/cmdline/commands/halt.py
+++ b/deluge/ui/console/cmdline/commands/halt.py
@@ -28,4 +28,8 @@ class Command(BaseCommand):
def on_shutdown_fail(reason):
self.console.write('{!error!}Unable to shutdown daemon: %s' % reason)
- return client.daemon.shutdown().addCallback(on_shutdown).addErrback(on_shutdown_fail)
+ return (
+ client.daemon.shutdown()
+ .addCallback(on_shutdown)
+ .addErrback(on_shutdown_fail)
+ )
diff --git a/deluge/ui/console/cmdline/commands/help.py b/deluge/ui/console/cmdline/commands/help.py
index df917f177..2711eea99 100644
--- a/deluge/ui/console/cmdline/commands/help.py
+++ b/deluge/ui/console/cmdline/commands/help.py
@@ -25,7 +25,9 @@ class Command(BaseCommand):
"""Displays help on other commands"""
def add_arguments(self, parser):
- parser.add_argument('commands', metavar='<command>', nargs='*', help=_('One or more commands'))
+ parser.add_argument(
+ 'commands', metavar='<command>', nargs='*', help=_('One or more commands')
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
@@ -51,8 +53,15 @@ class Command(BaseCommand):
if cmd in self._commands[cmd].aliases:
continue
parser = self._commands[cmd].create_parser()
- cmd_doc = '{!info!}' + '%-9s' % self._commands[cmd].name_with_alias + '{!input!} - '\
- + self._commands[cmd].__doc__ + '\n ' + parser.format_usage() or ''
+ cmd_doc = (
+ '{!info!}'
+ + '%-9s' % self._commands[cmd].name_with_alias
+ + '{!input!} - '
+ + self._commands[cmd].__doc__
+ + '\n '
+ + parser.format_usage()
+ or ''
+ )
cmds_doc += parser.formatter.format_colors(cmd_doc)
self.console.write(cmds_doc)
self.console.write(' ')
diff --git a/deluge/ui/console/cmdline/commands/info.py b/deluge/ui/console/cmdline/commands/info.py
index 44b1e4f27..02455da69 100644
--- a/deluge/ui/console/cmdline/commands/info.py
+++ b/deluge/ui/console/cmdline/commands/info.py
@@ -17,9 +17,19 @@ import deluge.ui.console.utils.colors as colors
from deluge.common import TORRENT_STATE, fsize, fspeed
from deluge.ui.client import client
from deluge.ui.common import FILE_PRIORITY
-from deluge.ui.console.utils.format_utils import (f_progressbar, f_seedrank_dash, format_date_never, format_progress,
- format_time, ftotal_sized, pad_string, remove_formatting,
- shorten_hash, strwidth, trim_string)
+from deluge.ui.console.utils.format_utils import (
+ f_progressbar,
+ f_seedrank_dash,
+ format_date_never,
+ format_progress,
+ format_time,
+ ftotal_sized,
+ pad_string,
+ remove_formatting,
+ shorten_hash,
+ strwidth,
+ trim_string,
+)
from . import BaseCommand
@@ -83,31 +93,58 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
- '-v', '--verbose', action='store_true', default=False, dest='verbose',
+ '-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',
+ '-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',
+ '-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',
+ '--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='*',
+ '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,
+ self.name,
+ prog=self.name,
+ help=self.__doc__,
+ description=self.__doc__,
+ epilog=self.epilog,
)
self.add_arguments(parser)
@@ -134,10 +171,16 @@ class Command(BaseCommand):
sort_reverse = False
if sort_key not in STATUS_KEYS:
self.console.write('')
- self.console.write('{!error!}Unknown sort key: ' + sort_key + ', will sort on name')
+ self.console.write(
+ '{!error!}Unknown sort key: ' + sort_key + ', will sort on name'
+ )
sort_key = 'name'
sort_reverse = False
- for key, value in sorted(list(status.items()), key=lambda x: x[1].get(sort_key), reverse=sort_reverse):
+ for key, value in sorted(
+ list(status.items()),
+ key=lambda x: x[1].get(sort_key),
+ reverse=sort_reverse,
+ ):
self.show_info(key, status[key], options.verbose, options.detailed)
def on_torrents_status_fail(reason):
@@ -189,7 +232,9 @@ class Command(BaseCommand):
col_priority = ' {!info!}Priority: '
- file_priority = FILE_PRIORITY[status['file_priorities'][index]].replace('Priority', '')
+ file_priority = FILE_PRIORITY[status['file_priorities'][index]].replace(
+ 'Priority', ''
+ )
if status['file_progress'][index] != 1.0:
if file_priority == 'Do Not Download':
col_priority += '{!error!}'
@@ -206,7 +251,9 @@ class Command(BaseCommand):
# Check how much space we've got left after writing all the info
space_left = cols - tlen(col_all_info)
# And how much we will potentially have with the longest possible column
- maxlen_space_left = cols - tlen(' (1000.0 MiB) 100.00% Priority: Do Not Download')
+ maxlen_space_left = cols - tlen(
+ ' (1000.0 MiB) 100.00% Priority: Do Not Download'
+ )
if maxlen_space_left > tlen(col_filename) + 1:
# If there is enough space, pad it all nicely
col_all_info = ''
@@ -221,7 +268,9 @@ class Command(BaseCommand):
col_all_info += col_priority
col_all_info += ' ' * spaces_to_add
# And remember to put it to the left!
- col_filename = pad_string(col_filename, maxlen_space_left - 2, side='right')
+ col_filename = pad_string(
+ col_filename, maxlen_space_left - 2, side='right'
+ )
elif space_left > tlen(col_filename) + 1:
# If there is enough space, put the info to the right
col_filename = pad_string(col_filename, space_left - 2, side='right')
@@ -250,7 +299,10 @@ class Command(BaseCommand):
s += peer['ip']
else:
# IPv6
- s += '[%s]:%s' % (':'.join(peer['ip'].split(':')[:-1]), peer['ip'].split(':')[-1])
+ s += '[%s]:%s' % (
+ ':'.join(peer['ip'].split(':')[:-1]),
+ peer['ip'].split(':')[-1],
+ )
c = peer['client']
s += '\t' + c
@@ -287,29 +339,40 @@ class Command(BaseCommand):
if verbose or detailed:
self.console.write('{!info!}Name: {!input!}%s' % (status['name']))
self.console.write('{!info!}ID: {!input!}%s' % (torrent_id))
- s = '{!info!}State: %s%s' % (colors.state_color[status['state']], status['state'])
+ s = '{!info!}State: %s%s' % (
+ colors.state_color[status['state']],
+ status['state'],
+ )
# Only show speed if active
if status['state'] in ('Seeding', 'Downloading'):
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'):
- s = '{!info!}Seeds: {!input!}%s (%s)' % (status['num_seeds'], status['total_seeds'])
+ s = '{!info!}Seeds: {!input!}%s (%s)' % (
+ status['num_seeds'],
+ status['total_seeds'],
+ )
s += sep
- s += '{!info!}Peers: {!input!}%s (%s)' % (status['num_peers'], status['total_peers'])
+ s += '{!info!}Peers: {!input!}%s (%s)' % (
+ status['num_peers'],
+ status['total_peers'],
+ )
s += sep
- s += '{!info!}Availability: {!input!}%.2f' % status['distributed_copies']
+ 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)
@@ -320,9 +383,13 @@ class Command(BaseCommand):
else:
s = '{!info!}Size: {!input!}%s/%s' % (total_done, total_size)
s += sep
- s += '{!info!}Downloaded: {!input!}%s' % fsize(status['all_time_download'], shortform=True)
+ s += '{!info!}Downloaded: {!input!}%s' % fsize(
+ status['all_time_download'], shortform=True
+ )
s += sep
- s += '{!info!}Uploaded: {!input!}%s' % fsize(status['total_uploaded'], shortform=True)
+ s += '{!info!}Uploaded: {!input!}%s' % fsize(
+ status['total_uploaded'], shortform=True
+ )
s += sep
s += '{!info!}Share Ratio: {!input!}%.2f' % status['ratio']
self.console.write(s)
@@ -334,20 +401,26 @@ class Command(BaseCommand):
s += '{!info!}Active: {!input!}%s' % format_time(status['active_time'])
self.console.write(s)
- s = '{!info!}Last Transfer: {!input!}%s' % format_time(status['time_since_transfer'])
+ 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']
self.console.write(s)
- self.console.write('{!info!}Tracker status: {!input!}%s' % status['tracker_status'])
+ self.console.write(
+ '{!info!}Tracker status: {!input!}%s' % status['tracker_status']
+ )
if not status['is_finished']:
- pbar = f_progressbar(status['progress'], cols - (13 + len('%.2f%%' % status['progress'])))
+ pbar = f_progressbar(
+ status['progress'], cols - (13 + len('%.2f%%' % status['progress']))
+ )
s = '{!info!}Progress: {!input!}%.2f%% %s' % (status['progress'], pbar)
self.console.write(s)
@@ -363,7 +436,10 @@ class Command(BaseCommand):
up_color = colors.state_color['Seeding']
down_color = colors.state_color['Downloading']
- s = '%s%s' % (colors.state_color[status['state']], '[' + status['state'][0] + ']')
+ s = '%s%s' % (
+ colors.state_color[status['state']],
+ '[' + status['state'][0] + ']',
+ )
s += ' {!info!}' + format_progress(status['progress']).rjust(6, ' ')
s += ' {!input!}%s' % (status['name'])
@@ -380,7 +456,9 @@ class Command(BaseCommand):
self.console.write(s)
dl_info = '{!info!}DL: {!input!}'
- dl_info += '%s' % ftotal_sized(status['all_time_download'], status['total_payload_download'])
+ dl_info += '%s' % ftotal_sized(
+ status['all_time_download'], status['total_payload_download']
+ )
if status['download_payload_rate'] > 0:
dl_info += ' @ %s%s' % (
@@ -389,7 +467,9 @@ class Command(BaseCommand):
)
ul_info = ' {!info!}UL: {!input!}'
- ul_info += '%s' % ftotal_sized(status['total_uploaded'], status['total_payload_upload'])
+ ul_info += '%s' % ftotal_sized(
+ status['total_uploaded'], status['total_payload_upload']
+ )
if status['upload_payload_rate'] > 0:
ul_info += ' @ %s%s' % (
up_color,
diff --git a/deluge/ui/console/cmdline/commands/manage.py b/deluge/ui/console/cmdline/commands/manage.py
index 8f8349679..2de921969 100644
--- a/deluge/ui/console/cmdline/commands/manage.py
+++ b/deluge/ui/console/cmdline/commands/manage.py
@@ -44,14 +44,28 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
- 'torrent', metavar='<torrent>',
+ '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'))
+ 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')
+ )
get_group = parser.add_argument_group('getting values')
- get_group.add_argument('keys', metavar='<keys>', nargs='*', help=_('one or more keys separated by space'))
+ get_group.add_argument(
+ 'keys',
+ metavar='<keys>',
+ nargs='*',
+ help=_('one or more keys separated by space'),
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
@@ -61,7 +75,6 @@ class Command(BaseCommand):
return self._get_option(options)
def _get_option(self, options):
-
def on_torrents_status(status):
for torrentid, data in status.items():
self.console.write('')
@@ -94,7 +107,7 @@ class Command(BaseCommand):
def _set_option(self, options):
deferred = defer.Deferred()
key = options.set
- val = ' ' .join(options.values)
+ val = ' '.join(options.values)
torrent_ids = self.console.match_torrent(options.torrent)
if key not in torrent_options:
@@ -107,8 +120,12 @@ class Command(BaseCommand):
self.console.write('{!success!}Torrent option successfully updated.')
deferred.callback(True)
- self.console.write('Setting %s to %s for torrents %s..' % (key, val, torrent_ids))
- client.core.set_torrent_options(torrent_ids, {key: val}).addCallback(on_set_config)
+ self.console.write(
+ 'Setting %s to %s for torrents %s..' % (key, val, torrent_ids)
+ )
+ client.core.set_torrent_options(torrent_ids, {key: val}).addCallback(
+ on_set_config
+ )
return deferred
def complete(self, line):
diff --git a/deluge/ui/console/cmdline/commands/move.py b/deluge/ui/console/cmdline/commands/move.py
index 637adbd54..13e475e6f 100644
--- a/deluge/ui/console/cmdline/commands/move.py
+++ b/deluge/ui/console/cmdline/commands/move.py
@@ -24,14 +24,24 @@ class Command(BaseCommand):
"""Move torrents' storage location"""
def add_arguments(self, parser):
- parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+', help=_('One or more torrent ids'))
- parser.add_argument('path', metavar='<path>', help=_('The path to move the torrents to'))
+ parser.add_argument(
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
+ help=_('One or more torrent ids'),
+ )
+ parser.add_argument(
+ 'path', metavar='<path>', help=_('The path to move the torrents to')
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
if os.path.exists(options.path) and not os.path.isdir(options.path):
- self.console.write('{!error!}Cannot Move Download Folder: %s exists and is not a directory' % options.path)
+ self.console.write(
+ '{!error!}Cannot Move Download Folder: %s exists and is not a directory'
+ % options.path
+ )
return
ids = []
diff --git a/deluge/ui/console/cmdline/commands/pause.py b/deluge/ui/console/cmdline/commands/pause.py
index fa5ba7d13..1f7ef31a0 100644
--- a/deluge/ui/console/cmdline/commands/pause.py
+++ b/deluge/ui/console/cmdline/commands/pause.py
@@ -18,11 +18,14 @@ from . import BaseCommand
class Command(BaseCommand):
"""Pause torrents"""
+
usage = 'pause [ * | <torrent-id> [<torrent-id> ...] ]'
def add_arguments(self, parser):
parser.add_argument(
- 'torrent_ids', metavar='<torrent-id>', nargs='+',
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
help=_('One or more torrent ids. Use "*" to pause all torrents'),
)
diff --git a/deluge/ui/console/cmdline/commands/plugin.py b/deluge/ui/console/cmdline/commands/plugin.py
index b9d59173a..fafc77afd 100644
--- a/deluge/ui/console/cmdline/commands/plugin.py
+++ b/deluge/ui/console/cmdline/commands/plugin.py
@@ -21,20 +21,38 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
- '-l', '--list', action='store_true', default=False, dest='list',
+ '-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',
+ '-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',
+ '-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('-i', '--install', help=_('Install a plugin from an .egg file'))
+ parser.add_argument(
+ '-i', '--install', help=_('Install a plugin from an .egg file')
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
@@ -45,6 +63,7 @@ class Command(BaseCommand):
return
elif options.list:
+
def on_available_plugins(result):
self.console.write('{!info!}Available Plugins:')
for p in result:
@@ -53,6 +72,7 @@ class Command(BaseCommand):
return client.core.get_available_plugins().addCallback(on_available_plugins)
elif options.show:
+
def on_enabled_plugins(result):
self.console.write('{!info!}Enabled Plugins:')
for p in result:
@@ -61,6 +81,7 @@ class Command(BaseCommand):
return client.core.get_enabled_plugins().addCallback(on_enabled_plugins)
elif options.enable:
+
def on_available_plugins(result):
plugins = {}
for p in result:
@@ -72,6 +93,7 @@ class Command(BaseCommand):
return client.core.get_available_plugins().addCallback(on_available_plugins)
elif options.disable:
+
def on_enabled_plugins(result):
plugins = {}
for p in result:
@@ -107,9 +129,15 @@ class Command(BaseCommand):
client.core.upload_plugin(filename, filedump)
client.core.rescan_plugins()
except Exception:
- self.console.write('{!error!}An error occurred, plugin was not installed')
+ self.console.write(
+ '{!error!}An error occurred, plugin was not installed'
+ )
- self.console.write('{!green!}Plugin was successfully installed: %s' % filename)
+ self.console.write(
+ '{!green!}Plugin was successfully installed: %s' % filename
+ )
def complete(self, line):
- return component.get('ConsoleUI').tab_complete_path(line, ext='.egg', sort='name', dirs_first=-1)
+ return component.get('ConsoleUI').tab_complete_path(
+ line, ext='.egg', sort='name', dirs_first=-1
+ )
diff --git a/deluge/ui/console/cmdline/commands/quit.py b/deluge/ui/console/cmdline/commands/quit.py
index 6c8895b00..261a01a9b 100644
--- a/deluge/ui/console/cmdline/commands/quit.py
+++ b/deluge/ui/console/cmdline/commands/quit.py
@@ -17,6 +17,7 @@ from . import BaseCommand
class Command(BaseCommand):
"""Exit the client"""
+
aliases = ['exit']
interactive_only = True
diff --git a/deluge/ui/console/cmdline/commands/recheck.py b/deluge/ui/console/cmdline/commands/recheck.py
index 49f196626..c9b6360c9 100644
--- a/deluge/ui/console/cmdline/commands/recheck.py
+++ b/deluge/ui/console/cmdline/commands/recheck.py
@@ -17,10 +17,16 @@ from . import BaseCommand
class Command(BaseCommand):
"""Forces a recheck of the torrent data"""
+
usage = 'recheck [ * | <torrent-id> [<torrent-id> ...] ]'
def add_arguments(self, parser):
- parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+', help=_('One or more torrent ids'))
+ parser.add_argument(
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
+ help=_('One or more torrent ids'),
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
diff --git a/deluge/ui/console/cmdline/commands/resume.py b/deluge/ui/console/cmdline/commands/resume.py
index 8a2632264..1f62c5f00 100644
--- a/deluge/ui/console/cmdline/commands/resume.py
+++ b/deluge/ui/console/cmdline/commands/resume.py
@@ -18,11 +18,14 @@ from . import BaseCommand
class Command(BaseCommand):
"""Resume torrents"""
+
usage = _('Usage: resume [ * | <torrent-id> [<torrent-id> ...] ]')
def add_arguments(self, parser):
parser.add_argument(
- 'torrent_ids', metavar='<torrent-id>', nargs='+',
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
help=_('One or more torrent ids. Use "*" to resume all torrents'),
)
diff --git a/deluge/ui/console/cmdline/commands/rm.py b/deluge/ui/console/cmdline/commands/rm.py
index a2d431c4d..ff3125d81 100644
--- a/deluge/ui/console/cmdline/commands/rm.py
+++ b/deluge/ui/console/cmdline/commands/rm.py
@@ -22,33 +22,50 @@ log = logging.getLogger(__name__)
class Command(BaseCommand):
"""Remove a torrent"""
+
aliases = ['del']
def add_arguments(self, parser):
parser.add_argument(
- '--remove_data', action='store_true', default=False,
+ '--remove_data',
+ action='store_true',
+ default=False,
help=_('Also removes the torrent data'),
)
parser.add_argument(
- '-c', '--confirm', action='store_true', default=False,
+ '-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'))
+ parser.add_argument(
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
+ help=_('One or more torrent ids'),
+ )
def handle(self, options):
self.console = component.get('ConsoleUI')
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))
- self.console.write(_('Confirm with -c to remove the listed torrents (Count: %d)') % len(torrent_ids))
+ self.console.write(
+ _('Confirm with -c to remove the listed torrents (Count: %d)')
+ % len(torrent_ids)
+ )
return
def on_removed_finished(errors):
diff --git a/deluge/ui/console/cmdline/commands/status.py b/deluge/ui/console/cmdline/commands/status.py
index 2f34ede95..948ad6b94 100644
--- a/deluge/ui/console/cmdline/commands/status.py
+++ b/deluge/ui/console/cmdline/commands/status.py
@@ -27,14 +27,22 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
- '-r', '--raw', action='store_true', default=False, dest='raw',
+ '-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)',
+ '(useful for scripts that want to do their own parsing)'
),
)
parser.add_argument(
- '-n', '--no-torrents', action='store_false', default=True, dest='show_torrents',
+ '-n',
+ '--no-torrents',
+ action='store_false',
+ default=True,
+ dest='show_torrents',
help=_('Do not show torrent status (Improves command speed)'),
)
@@ -56,7 +64,9 @@ class Command(BaseCommand):
deferreds = []
- ds = client.core.get_session_status(['num_peers', 'payload_upload_rate', 'payload_download_rate', 'dht_nodes'])
+ ds = client.core.get_session_status(
+ ['num_peers', 'payload_upload_rate', 'payload_download_rate', 'dht_nodes']
+ )
ds.addCallback(on_session_status)
deferreds.append(ds)
@@ -71,11 +81,20 @@ class Command(BaseCommand):
def print_status(self, *args):
self.console.set_batch_write(True)
if self.raw:
- self.console.write('{!info!}Total upload: %f' % self.status['payload_upload_rate'])
- self.console.write('{!info!}Total download: %f' % self.status['payload_download_rate'])
+ self.console.write(
+ '{!info!}Total upload: %f' % self.status['payload_upload_rate']
+ )
+ self.console.write(
+ '{!info!}Total download: %f' % self.status['payload_download_rate']
+ )
else:
- self.console.write('{!info!}Total upload: %s' % fspeed(self.status['payload_upload_rate']))
- self.console.write('{!info!}Total download: %s' % fspeed(self.status['payload_download_rate']))
+ self.console.write(
+ '{!info!}Total upload: %s' % fspeed(self.status['payload_upload_rate'])
+ )
+ self.console.write(
+ '{!info!}Total download: %s'
+ % fspeed(self.status['payload_download_rate'])
+ )
self.console.write('{!info!}DHT Nodes: %i' % self.status['dht_nodes'])
if isinstance(self.torrents, int):
diff --git a/deluge/ui/console/cmdline/commands/update_tracker.py b/deluge/ui/console/cmdline/commands/update_tracker.py
index f0848bced..591b95192 100644
--- a/deluge/ui/console/cmdline/commands/update_tracker.py
+++ b/deluge/ui/console/cmdline/commands/update_tracker.py
@@ -18,12 +18,15 @@ from . import BaseCommand
class Command(BaseCommand):
"""Update tracker for torrent(s)"""
+
usage = 'update_tracker [ * | <torrent-id> [<torrent-id> ...] ]'
aliases = ['reannounce']
def add_arguments(self, parser):
parser.add_argument(
- 'torrent_ids', metavar='<torrent-id>', nargs='+',
+ 'torrent_ids',
+ metavar='<torrent-id>',
+ nargs='+',
help='One or more torrent ids. "*" updates all torrents',
)
diff --git a/deluge/ui/console/console.py b/deluge/ui/console/console.py
index 893caf548..99d6ea72c 100644
--- a/deluge/ui/console/console.py
+++ b/deluge/ui/console/console.py
@@ -28,13 +28,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',
+ 'deluge.ui.console.cmdline.commands.%s' % name, {}, {}, ['Command']
+ ),
+ 'Command',
)()
command._name = name
return command
@@ -69,48 +68,74 @@ class Console(UI):
cmd_description = """Console or command-line user interface"""
def __init__(self, *args, **kwargs):
- super(Console, self).__init__('console', *args, log_stream=LogStream(), **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.',
+ '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',
+ '-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',
+ '-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',
+ '-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',
+ '-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)
+ 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,
+ 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),
+ 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'),
+ title=_('Console Commands'),
+ help=_('Description'),
description=_('The following console commands are available:'),
- metavar=_('Command'), dest='command',
+ 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):
self.console_cmds[cmd].add_subparser(subparsers)
@@ -137,6 +162,8 @@ class Console(UI):
raise
return deluge.common.run_profiled(
- run, self.options, output_file=self.options.profile,
+ run,
+ self.options,
+ output_file=self.options.profile,
do_profile=self.options.profile,
)
diff --git a/deluge/ui/console/main.py b/deluge/ui/console/main.py
index 0edbe6034..23965bbb2 100644
--- a/deluge/ui/console/main.py
+++ b/deluge/ui/console/main.py
@@ -68,7 +68,6 @@ DEFAULT_CONSOLE_PREFS = {
class ConsoleUI(component.Component, TermResizeHandler):
-
def __init__(self, options, cmds, log_stream):
component.Component.__init__(self, 'ConsoleUI')
TermResizeHandler.__init__(self)
@@ -126,14 +125,17 @@ class ConsoleUI(component.Component, TermResizeHandler):
else:
# Interactive
if deluge.common.windows_check():
- print("""\nDeluge-console does not run in interactive mode on Windows. \n
+ print(
+ """\nDeluge-console does not run in interactive mode on Windows. \n
Please use commands from the command line, e.g.:\n
deluge-console.exe help
deluge-console.exe info
deluge-console.exe "add --help"
deluge-console.exe "add -p c:\\mytorrents c:\\new.torrent"
-""")
+"""
+ )
else:
+
class ConsoleLog(object):
def write(self, data):
pass
@@ -153,12 +155,15 @@ Please use commands from the command line, e.g.:\n
# We use the curses.wrapper function to prevent the console from getting
# messed up if an uncaught exception is experienced.
from curses import wrapper
+
wrapper(self.run)
def quit(self):
if client.connected():
+
def on_disconnect(result):
reactor.stop()
+
return client.disconnect().addCallback(on_disconnect)
else:
try:
@@ -169,6 +174,7 @@ Please use commands from the command line, e.g.:\n
def exec_args(self, options):
"""Execute console commands from command line."""
from deluge.ui.console.cmdline.command import Commander
+
commander = Commander(self._commands)
def on_connect(result):
@@ -179,6 +185,7 @@ Please use commands from the command line, e.g.:\n
def exec_command(result, cmd):
return commander.exec_command(cmd)
+
d = defer.succeed(None)
for command in options.parsed_cmds:
if command.command in ('quit', 'exit'):
@@ -191,6 +198,7 @@ Please use commands from the command line, e.g.:\n
# any of the commands.
self.started_deferred.addCallback(on_started)
return self.started_deferred
+
d = self.start_console()
d.addCallback(on_components_started)
return d
@@ -200,7 +208,10 @@ Please use commands from the command line, e.g.:\n
rm = reason.getErrorMessage()
else:
rm = reason.value.message
- print('Could not connect to daemon: %s:%s\n %s' % (options.daemon_addr, options.daemon_port, rm))
+ print(
+ 'Could not connect to daemon: %s:%s\n %s'
+ % (options.daemon_addr, options.daemon_port, rm)
+ )
commander.do_command('quit')
d = None
@@ -209,9 +220,17 @@ Please use commands from the command line, e.g.:\n
else:
log.info(
'connect: host=%s, port=%s, username=%s, password=%s',
- options.daemon_addr, options.daemon_port, options.daemon_user, options.daemon_pass,
+ 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 = client.connect(options.daemon_addr, options.daemon_port, options.daemon_user, options.daemon_pass)
d.addCallback(on_connect)
d.addErrback(on_connect_fail)
return d
@@ -227,23 +246,34 @@ Please use commands from the command line, e.g.:\n
# pass it the function that handles commands
colors.init_colors()
self.stdscr = stdscr
- self.config = ConfigManager('console.conf', defaults=DEFAULT_CONSOLE_PREFS, file_version=2)
+ self.config = ConfigManager(
+ 'console.conf', defaults=DEFAULT_CONSOLE_PREFS, file_version=2
+ )
self.config.run_converter((0, 1), 2, self._migrate_config_1_to_2)
self.statusbars = StatusBars()
from deluge.ui.console.modes.connectionmanager import ConnectionManager
+
self.register_mode(ConnectionManager(stdscr, self.encoding), set_mode=True)
torrentlist = self.register_mode(TorrentList(self.stdscr, self.encoding))
self.register_mode(CmdLine(self.stdscr, self.encoding))
self.register_mode(EventView(torrentlist, self.stdscr, self.encoding))
- self.register_mode(TorrentDetail(torrentlist, self.stdscr, self.config, self.encoding))
- self.register_mode(Preferences(torrentlist, self.stdscr, self.config, self.encoding))
- self.register_mode(AddTorrents(torrentlist, self.stdscr, self.config, self.encoding))
+ self.register_mode(
+ TorrentDetail(torrentlist, self.stdscr, self.config, self.encoding)
+ )
+ self.register_mode(
+ Preferences(torrentlist, self.stdscr, self.config, self.encoding)
+ )
+ self.register_mode(
+ AddTorrents(torrentlist, self.stdscr, self.config, self.encoding)
+ )
self.eventlog = EventLog()
- self.active_mode.topbar = '{!status!}Deluge ' + deluge.common.get_version() + ' Console'
+ self.active_mode.topbar = (
+ '{!status!}Deluge ' + deluge.common.get_version() + ' Console'
+ )
self.active_mode.bottombar = '{!status!}'
self.active_mode.refresh()
# Start the twisted mainloop
@@ -275,6 +305,7 @@ Please use commands from the command line, e.g.:\n
def on_mode_paused(result, mode, *args):
from deluge.ui.console.widgets.popup import PopupsHandler
+
if isinstance(mode, PopupsHandler):
if mode.popup is not None:
# If popups are not removed, they are still referenced in the memory
@@ -283,8 +314,10 @@ Please use commands from the command line, e.g.:\n
# 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,
+ ' Ensure all popups are removed on pause!',
+ mode.popup.title,
)
+
d.addCallback(on_mode_paused, self.active_mode)
reactor.removeReader(self.active_mode)
@@ -312,6 +345,7 @@ Please use commands from the command line, e.g.:\n
func()
else:
self.messages.append(('Error', error_smg))
+
component.stop(['TorrentList']).addCallback(on_stop)
def is_active_mode(self, mode):
@@ -319,7 +353,15 @@ Please use commands from the command line, e.g.:\n
def start_components(self):
def on_started(result):
- component.pause(['TorrentList', 'EventView', 'AddTorrents', 'TorrentDetail', 'Preferences'])
+ component.pause(
+ [
+ 'TorrentList',
+ 'EventView',
+ 'AddTorrents',
+ 'TorrentDetail',
+ 'Preferences',
+ ]
+ )
if self.interactive:
d = component.start().addCallback(on_started)
@@ -335,8 +377,10 @@ Please use commands from the command line, e.g.:\n
self.initialized = True
d = self.start_components()
else:
+
def on_stopped(result):
return component.start(['SessionProxy'])
+
d = component.stop(['SessionProxy']).addCallback(on_stopped)
return d
@@ -350,18 +394,23 @@ Please use commands from the command line, e.g.:\n
self.torrents.append((torrent_id, status['name']))
self.started_deferred.callback(True)
- client.core.get_torrents_status({'id': result}, ['name']).addCallback(on_torrents_status)
+ client.core.get_torrents_status({'id': result}, ['name']).addCallback(
+ on_torrents_status
+ )
d = client.core.get_session_state().addCallback(on_session_state)
# Register event handlers to keep the torrent list up-to-date
client.register_event_handler('TorrentAddedEvent', self.on_torrent_added_event)
- client.register_event_handler('TorrentRemovedEvent', self.on_torrent_removed_event)
+ client.register_event_handler(
+ 'TorrentRemovedEvent', self.on_torrent_removed_event
+ )
return d
def on_torrent_added_event(self, event, from_state=False):
def on_torrent_status(status):
self.torrents.append((event, status['name']))
+
client.core.get_torrent_status(event, ['name']).addCallback(on_torrent_status)
def on_torrent_removed_event(self, event):
@@ -402,7 +451,9 @@ Please use commands from the command line, e.g.:\n
matches = []
for tid, name in self.torrents:
deluge.common.decode_bytes(name, self.encoding)
- if getattr(tid, match_func, None)(string) or getattr(name, match_func, None)(string):
+ if getattr(tid, match_func, None)(string) or getattr(
+ name, match_func, None
+ )(string):
matches.append(tid)
return matches
@@ -413,18 +464,25 @@ Please use commands from the command line, e.g.:\n
return None
def set_batch_write(self, batch):
- if self.interactive and isinstance(self.active_mode, deluge.ui.console.modes.cmdline.CmdLine):
+ if self.interactive and isinstance(
+ self.active_mode, deluge.ui.console.modes.cmdline.CmdLine
+ ):
return self.active_mode.set_batch_write(batch)
def tab_complete_torrent(self, line):
- if self.interactive and isinstance(self.active_mode, deluge.ui.console.modes.cmdline.CmdLine):
+ if self.interactive and isinstance(
+ self.active_mode, deluge.ui.console.modes.cmdline.CmdLine
+ ):
return self.active_mode.tab_complete_torrent(line)
- 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):
+ 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,
+ line, path_type=path_type, ext=ext, sort=sort, dirs_first=dirs_first
)
def on_client_disconnect(self):
@@ -456,6 +514,7 @@ Please use commands from the command line, e.g.:\n
and into sub categories. Some keys are also renamed to be consistent
with other UIs.
"""
+
def move_key(source, dest, source_key, dest_key=None):
if dest_key is None:
dest_key = source_key
@@ -463,28 +522,71 @@ Please use commands from the command line, e.g.:\n
del source[source_key]
# These are moved to 'torrentview' sub dict
- for k in ['sort_primary', 'sort_secondary', 'move_selection', 'separate_complete']:
+ for k in [
+ 'sort_primary',
+ 'sort_secondary',
+ 'move_selection',
+ 'separate_complete',
+ ]:
move_key(config, config['torrentview'], k)
# These are moved to 'addtorrents' sub dict
- for k in ['show_misc_files', 'show_hidden_folders', 'sort_column', 'reverse_sort', 'last_path']:
+ for k in [
+ 'show_misc_files',
+ 'show_hidden_folders',
+ 'sort_column',
+ 'reverse_sort',
+ 'last_path',
+ ]:
move_key(config, config['addtorrents'], 'addtorrents_%s' % k, dest_key=k)
# These are moved to 'cmdline' sub dict
- for k in ['ignore_duplicate_lines', 'torrents_per_tab_press', 'third_tab_lists_all']:
+ for k in [
+ 'ignore_duplicate_lines',
+ 'torrents_per_tab_press',
+ 'third_tab_lists_all',
+ ]:
move_key(config, config['cmdline'], k)
- move_key(config, config['cmdline'], 'save_legacy_history', dest_key='save_command_history')
+ move_key(
+ config,
+ config['cmdline'],
+ 'save_legacy_history',
+ dest_key='save_command_history',
+ )
# Add key for localization
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',
+ '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',
@@ -499,6 +601,7 @@ Please use commands from the command line, e.g.:\n
}
from deluge.ui.console.modes.torrentlist.torrentview import default_columns
+
# These are moved to 'torrentview.columns' sub dict
for k in columns:
column_name = column_name_mapping.get(k, k)
@@ -506,9 +609,21 @@ Please use commands from the command line, e.g.:\n
if k == 'name':
config['torrentview']['columns'][column_name]['visible'] = True
else:
- move_key(config, config['torrentview']['columns'][column_name], 'show_%s' % k, dest_key='visible')
- move_key(config, config['torrentview']['columns'][column_name], '%s_width' % k, dest_key='width')
- config['torrentview']['columns'][column_name]['order'] = default_columns[column_name]['order']
+ move_key(
+ config,
+ config['torrentview']['columns'][column_name],
+ 'show_%s' % k,
+ dest_key='visible',
+ )
+ move_key(
+ config,
+ config['torrentview']['columns'][column_name],
+ '%s_width' % k,
+ dest_key='width',
+ )
+ config['torrentview']['columns'][column_name]['order'] = default_columns[
+ column_name
+ ]['order']
return config
@@ -517,6 +632,7 @@ class EventLog(component.Component):
"""
Prints out certain events as they are received from the core.
"""
+
def __init__(self):
component.Component.__init__(self, 'EventLog')
self.console = component.get('ConsoleUI')
@@ -524,15 +640,33 @@ class EventLog(component.Component):
self.date_change_format = 'On {!yellow!}%a, %d %b %Y{!input!} %Z:'
client.register_event_handler('TorrentAddedEvent', self.on_torrent_added_event)
- client.register_event_handler('PreTorrentRemovedEvent', self.on_torrent_removed_event)
- client.register_event_handler('TorrentStateChangedEvent', self.on_torrent_state_changed_event)
- client.register_event_handler('TorrentFinishedEvent', self.on_torrent_finished_event)
- client.register_event_handler('NewVersionAvailableEvent', self.on_new_version_available_event)
- client.register_event_handler('SessionPausedEvent', self.on_session_paused_event)
- client.register_event_handler('SessionResumedEvent', self.on_session_resumed_event)
- client.register_event_handler('ConfigValueChangedEvent', self.on_config_value_changed_event)
- client.register_event_handler('PluginEnabledEvent', self.on_plugin_enabled_event)
- client.register_event_handler('PluginDisabledEvent', self.on_plugin_disabled_event)
+ client.register_event_handler(
+ 'PreTorrentRemovedEvent', self.on_torrent_removed_event
+ )
+ client.register_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrent_state_changed_event
+ )
+ client.register_event_handler(
+ 'TorrentFinishedEvent', self.on_torrent_finished_event
+ )
+ client.register_event_handler(
+ 'NewVersionAvailableEvent', self.on_new_version_available_event
+ )
+ client.register_event_handler(
+ 'SessionPausedEvent', self.on_session_paused_event
+ )
+ client.register_event_handler(
+ 'SessionResumedEvent', self.on_session_resumed_event
+ )
+ client.register_event_handler(
+ 'ConfigValueChangedEvent', self.on_config_value_changed_event
+ )
+ client.register_event_handler(
+ 'PluginEnabledEvent', self.on_plugin_enabled_event
+ )
+ client.register_event_handler(
+ 'PluginDisabledEvent', self.on_plugin_disabled_event
+ )
self.previous_time = time.localtime(0)
@@ -541,16 +675,22 @@ class EventLog(component.Component):
return
def on_torrent_status(status):
- self.write('{!green!}Torrent Added: {!info!}%s ({!cyan!}%s{!info!})' %
- (status['name'], torrent_id))
+ self.write(
+ '{!green!}Torrent Added: {!info!}%s ({!cyan!}%s{!info!})'
+ % (status['name'], torrent_id)
+ )
# Write out what state the added torrent took
self.on_torrent_state_changed_event(torrent_id, status['state'])
- client.core.get_torrent_status(torrent_id, ['name', 'state']).addCallback(on_torrent_status)
+ client.core.get_torrent_status(torrent_id, ['name', 'state']).addCallback(
+ on_torrent_status
+ )
def on_torrent_removed_event(self, torrent_id):
- self.write('{!red!}Torrent Removed: {!info!}%s ({!cyan!}%s{!info!})' %
- (self.console.get_torrent_name(torrent_id), torrent_id))
+ self.write(
+ '{!red!}Torrent Removed: {!info!}%s ({!cyan!}%s{!info!})'
+ % (self.console.get_torrent_name(torrent_id), torrent_id)
+ )
def on_torrent_state_changed_event(self, torrent_id, state):
# It's probably a new torrent, ignore it
@@ -566,19 +706,20 @@ class EventLog(component.Component):
if not t_name:
return
- self.write('%s: {!info!}%s ({!cyan!}%s{!info!})' %
- (state, t_name, torrent_id))
+ self.write('%s: {!info!}%s ({!cyan!}%s{!info!})' % (state, t_name, torrent_id))
def on_torrent_finished_event(self, torrent_id):
if component.get('TorrentList').config['ring_bell']:
import curses.beep
+
curses.beep()
- self.write('{!info!}Torrent Finished: %s ({!cyan!}%s{!info!})' %
- (self.console.get_torrent_name(torrent_id), torrent_id))
+ self.write(
+ '{!info!}Torrent Finished: %s ({!cyan!}%s{!info!})'
+ % (self.console.get_torrent_name(torrent_id), torrent_id)
+ )
def on_new_version_available_event(self, version):
- self.write('{!input!}New Deluge version available: {!info!}%s' %
- (version))
+ self.write('{!input!}New Deluge version available: {!info!}%s' % (version))
def on_session_paused_event(self):
self.write('{!input!}Session Paused')
diff --git a/deluge/ui/console/modes/add_util.py b/deluge/ui/console/modes/add_util.py
index 4138a2f5f..6ebfd9957 100644
--- a/deluge/ui/console/modes/add_util.py
+++ b/deluge/ui/console/modes/add_util.py
@@ -30,7 +30,9 @@ def _bracket_fixup(path):
while path.find(unichr(sentinal)) != -1:
sentinal += 1
if sentinal > 65535:
- log.error('Cannot fix brackets in path, path contains all possible sentinal characters')
+ log.error(
+ 'Cannot fix brackets in path, path contains all possible sentinal characters'
+ )
return path
newpath = path.replace(']', unichr(sentinal))
newpath = newpath.replace('[', '[[]')
@@ -44,8 +46,12 @@ def add_torrent(t_file, options, success_cb, fail_cb, ress):
t_options['download_location'] = os.path.expanduser(options['path'])
t_options['add_paused'] = options['add_paused']
- is_url = (options['path_type'] != 1) and (deluge.common.is_url(t_file) or options['path_type'] == 2)
- is_magnet = not(is_url) and (options['path_type'] != 1) and deluge.common.is_magnet(t_file)
+ is_url = (options['path_type'] != 1) and (
+ deluge.common.is_url(t_file) or options['path_type'] == 2
+ )
+ is_magnet = (
+ not (is_url) and (options['path_type'] != 1) and deluge.common.is_magnet(t_file)
+ )
if is_url or is_magnet:
files = [t_file]
@@ -59,9 +65,13 @@ def add_torrent(t_file, options, success_cb, fail_cb, ress):
for f in files:
if is_url:
- client.core.add_torrent_url(f, t_options).addCallback(success_cb, f, ress).addErrback(fail_cb, f, ress)
+ client.core.add_torrent_url(f, t_options).addCallback(
+ success_cb, f, ress
+ ).addErrback(fail_cb, f, ress)
elif is_magnet:
- client.core.add_torrent_magnet(f, t_options).addCallback(success_cb, f, ress).addErrback(fail_cb, f, ress)
+ client.core.add_torrent_magnet(f, t_options).addCallback(
+ success_cb, f, ress
+ ).addErrback(fail_cb, f, ress)
else:
if not os.path.exists(f):
fail_cb('Does not exist', f, ress)
@@ -81,5 +91,5 @@ def add_torrent(t_file, options, success_cb, fail_cb, ress):
filedump = b64encode(_file.read())
client.core.add_torrent_file_async(
- filename, filedump, t_options,
+ filename, filedump, t_options
).addCallback(success_cb, f, ress).addErrback(fail_cb, f, ress)
diff --git a/deluge/ui/console/modes/addtorrents.py b/deluge/ui/console/modes/addtorrents.py
index 32892a60d..6b2c105d9 100644
--- a/deluge/ui/console/modes/addtorrents.py
+++ b/deluge/ui/console/modes/addtorrents.py
@@ -66,7 +66,6 @@ if a file is highlighted
class AddTorrents(BaseMode):
-
def __init__(self, parent_mode, stdscr, console_config, encoding=None):
self.console_config = console_config
self.parent_mode = parent_mode
@@ -108,7 +107,7 @@ class AddTorrents(BaseMode):
pass
def __refresh_listing(self):
- path = os.path.join(*self.path_stack[:self.path_stack_pos])
+ path = os.path.join(*self.path_stack[: self.path_stack_pos])
listing = os.listdir(path)
@@ -177,7 +176,9 @@ class AddTorrents(BaseMode):
self.raw_rows_dirs.sort(key=lambda r: r[0].lower())
if self.sort_column == 'name':
- self.raw_rows_files.sort(key=lambda r: r[0].lower(), reverse=self.reverse_sort)
+ self.raw_rows_files.sort(
+ key=lambda r: r[0].lower(), reverse=self.reverse_sort
+ )
elif self.sort_column == 'date':
self.raw_rows_files.sort(key=lambda r: r[2], reverse=self.reverse_sort)
self.raw_rows = self.raw_rows_dirs + self.raw_rows_files
@@ -287,7 +288,7 @@ class AddTorrents(BaseMode):
off += 1
# Render files and folders
- for i, row in enumerate(self.formatted_rows[self.view_offset:]):
+ for i, row in enumerate(self.formatted_rows[self.view_offset :]):
i += self.view_offset
# It's a folder
color_string = ''
@@ -347,14 +348,16 @@ class AddTorrents(BaseMode):
new_dir = self.path_stack_pos >= len(self.path_stack)
new_dir = new_dir or (dirname != self.path_stack[self.path_stack_pos])
if new_dir:
- self.path_stack = self.path_stack[:self.path_stack_pos]
+ self.path_stack = self.path_stack[: self.path_stack_pos]
self.path_stack.append(dirname)
- path = os.path.join(*self.path_stack[:self.path_stack_pos + 1])
+ path = os.path.join(*self.path_stack[: self.path_stack_pos + 1])
if not os.access(path, os.R_OK):
- self.path_stack = self.path_stack[:self.path_stack_pos]
- self.popup = MessagePopup(self, 'Error', '{!error!}Access denied: %s' % path)
+ self.path_stack = self.path_stack[: self.path_stack_pos]
+ self.popup = MessagePopup(
+ self, 'Error', '{!error!}Access denied: %s' % path
+ )
self.__refresh_listing()
return
@@ -368,7 +371,6 @@ class AddTorrents(BaseMode):
self.__refresh_listing()
def _show_add_dialog(self):
-
def _do_add(result, **kwargs):
ress = {'succ': 0, 'fail': 0, 'total': len(self.marked), 'fmsg': []}
@@ -377,20 +379,30 @@ class AddTorrents(BaseMode):
ress['fail'] += 1
ress['fmsg'].append('{!input!} * %s: {!error!}%s' % (t_file, msg))
if (ress['succ'] + ress['fail']) >= ress['total']:
- report_add_status(component.get('TorrentList'), ress['succ'], ress['fail'], ress['fmsg'])
+ report_add_status(
+ component.get('TorrentList'),
+ ress['succ'],
+ ress['fail'],
+ ress['fmsg'],
+ )
def success_cb(tid, t_file, ress):
if tid:
log.debug('added torrent: %s (%s)', t_file, tid)
ress['succ'] += 1
if (ress['succ'] + ress['fail']) >= ress['total']:
- report_add_status(component.get('TorrentList'), ress['succ'], ress['fail'], ress['fmsg'])
+ report_add_status(
+ component.get('TorrentList'),
+ ress['succ'],
+ ress['fail'],
+ ress['fmsg'],
+ )
else:
fail_cb('Already in session (probably)', t_file, ress)
for m in self.marked:
filename = m
- directory = os.path.join(*self.path_stack[:self.path_stack_pos])
+ directory = os.path.join(*self.path_stack[: self.path_stack_pos])
path = os.path.join(directory, filename)
with open(path, 'rb') as _file:
filedump = b64encode(_file.read())
@@ -403,7 +415,9 @@ class AddTorrents(BaseMode):
d.addCallback(success_cb, filename, ress)
d.addErrback(fail_cb, filename, ress)
- self.console_config['addtorrents']['last_path'] = os.path.join(*self.path_stack[:self.path_stack_pos])
+ self.console_config['addtorrents']['last_path'] = os.path.join(
+ *self.path_stack[: self.path_stack_pos]
+ )
self.console_config.save()
self.back_to_overview()
@@ -413,7 +427,9 @@ class AddTorrents(BaseMode):
ap = 0
else:
ap = 1
- self.popup = InputPopup(self, 'Add Torrents (Esc to cancel)', close_cb=_do_add, height_req=17)
+ self.popup = InputPopup(
+ self, 'Add Torrents (Esc to cancel)', close_cb=_do_add, height_req=17
+ )
msg = 'Adding torrent files:'
for i, m in enumerate(self.marked):
@@ -426,8 +442,12 @@ class AddTorrents(BaseMode):
self.popup.add_text(msg)
self.popup.add_spaces(1)
- self.popup.add_text_input('location', 'Download Folder:', config['download_location'], complete=True)
- self.popup.add_select_input('add_paused', 'Add Paused:', ['Yes', 'No'], [True, False], ap)
+ self.popup.add_text_input(
+ 'location', 'Download Folder:', config['download_location'], complete=True
+ )
+ self.popup.add_select_input(
+ 'add_paused', 'Add Paused:', ['Yes', 'No'], [True, False], ap
+ )
def _go_up(self):
# Go up in directory hierarchy
diff --git a/deluge/ui/console/modes/basemode.py b/deluge/ui/console/modes/basemode.py
index 6226d1bc1..6ad2a2c36 100644
--- a/deluge/ui/console/modes/basemode.py
+++ b/deluge/ui/console/modes/basemode.py
@@ -37,7 +37,6 @@ log = logging.getLogger(__name__)
class InputKeyHandler(object):
-
def __init__(self):
self._input_result = None
@@ -64,7 +63,6 @@ class InputKeyHandler(object):
class TermResizeHandler(object):
-
def __init__(self):
try:
signal.signal(signal.SIGWINCH, self.on_terminal_size)
@@ -73,10 +71,9 @@ class TermResizeHandler(object):
def on_terminal_size(self, *args):
# Get the new rows and cols value
- rows, cols = struct.unpack(
- 'hhhh',
- ioctl(0, termios.TIOCGWINSZ, b'\000' * 8),
- )[0:2]
+ rows, cols = struct.unpack('hhhh', ioctl(0, termios.TIOCGWINSZ, b'\000' * 8))[
+ 0:2
+ ]
curses.resizeterm(rows, cols)
return rows, cols
@@ -100,8 +97,9 @@ class CursesStdIO(object):
class BaseMode(CursesStdIO, component.Component):
-
- def __init__(self, stdscr, encoding=None, do_refresh=True, mode_name=None, depend=None):
+ def __init__(
+ self, stdscr, encoding=None, do_refresh=True, mode_name=None, depend=None
+ ):
"""
A mode that provides a curses screen designed to run as a reader in a twisted reactor.
This mode doesn't do much, just shows status bars and "Base Mode" on the screen
@@ -160,16 +158,28 @@ class BaseMode(CursesStdIO, component.Component):
return add_string(row, string, screen, self.encoding, **kwargs)
def draw_statusbars(
- self, top_row=0, bottom_row=-1, topbar=None, bottombar=None,
- bottombar_help=True, scr=None,
+ self,
+ top_row=0,
+ bottom_row=-1,
+ topbar=None,
+ bottombar=None,
+ bottombar_help=True,
+ scr=None,
):
self.add_string(top_row, topbar if topbar else self.statusbars.topbar, scr=scr)
bottombar = bottombar if bottombar else self.statusbars.bottombar
if bottombar_help:
if bottombar_help is True:
bottombar_help = self.help_hstr
- bottombar += ' ' * (self.cols - len(remove_formatting(bottombar)) -
- len(remove_formatting(bottombar_help))) + bottombar_help
+ bottombar += (
+ ' '
+ * (
+ self.cols
+ - len(remove_formatting(bottombar))
+ - len(remove_formatting(bottombar_help))
+ )
+ + bottombar_help
+ )
self.add_string(self.rows + bottom_row, bottombar, scr=scr)
# This mode doesn't do anything with popups
@@ -226,7 +236,9 @@ class BaseMode(CursesStdIO, component.Component):
curses.endwin()
-def add_string(row, fstring, screen, encoding, col=0, pad=True, pad_char=' ', trim='..', leaveok=0):
+def add_string(
+ row, fstring, screen, encoding, col=0, pad=True, pad_char=' ', trim='..', leaveok=0
+):
"""
Adds a string to the desired `:param:row`.
@@ -282,7 +294,7 @@ def add_string(row, fstring, screen, encoding, col=0, pad=True, pad_char=' ', tr
if col + len(string) > max_x:
remaining_chrs = max(0, max_x - col)
if trim:
- string = string[0:max(0, remaining_chrs - len(trim))] + trim
+ string = string[0 : max(0, remaining_chrs - len(trim))] + trim
else:
string = string[0:remaining_chrs]
@@ -333,7 +345,13 @@ def move_cursor(screen, row, col):
screen.move(row, col)
except curses.error as ex:
import traceback
+
log.warning(
'Error on screen.move(%s, %s): (curses.LINES: %s, curses.COLS: %s) Error: %s\nStack: %s',
- row, col, curses.LINES, curses.COLS, ex, ''.join(traceback.format_stack()),
+ row,
+ col,
+ curses.LINES,
+ curses.COLS,
+ ex,
+ ''.join(traceback.format_stack()),
)
diff --git a/deluge/ui/console/modes/cmdline.py b/deluge/ui/console/modes/cmdline.py
index 683f6be17..21236c3c7 100644
--- a/deluge/ui/console/modes/cmdline.py
+++ b/deluge/ui/console/modes/cmdline.py
@@ -22,7 +22,11 @@ from deluge.ui.console.cmdline.command import Commander
from deluge.ui.console.modes.basemode import BaseMode, move_cursor
from deluge.ui.console.utils import colors
from deluge.ui.console.utils import curses_util as util
-from deluge.ui.console.utils.format_utils import delete_alt_backspace, remove_formatting, strwidth
+from deluge.ui.console.utils.format_utils import (
+ delete_alt_backspace,
+ remove_formatting,
+ strwidth,
+)
try:
import curses
@@ -95,7 +99,6 @@ def commonprefix(m):
class CmdLine(BaseMode, Commander):
-
def __init__(self, stdscr, encoding=None):
# Get a handle to the main console
self.console = component.get('ConsoleUI')
@@ -246,8 +249,13 @@ class CmdLine(BaseMode, Commander):
if self.tab_completer:
# We only call the tab completer function if we're at the end of
# the input string on the cursor is on a space
- if self.input_cursor == len(self.input) or self.input[self.input_cursor] == ' ':
- self.input, self.input_cursor = self.tab_completer(self.input, self.input_cursor, self.tab_count)
+ if (
+ self.input_cursor == len(self.input)
+ or self.input[self.input_cursor] == ' '
+ ):
+ self.input, self.input_cursor = self.tab_completer(
+ self.input, self.input_cursor, self.tab_count
+ )
# We use the UP and DOWN keys to cycle through input history
elif c == curses.KEY_UP:
@@ -301,14 +309,25 @@ class CmdLine(BaseMode, Commander):
# Delete a character in the input string based on cursor position
elif c in [curses.KEY_BACKSPACE, util.KEY_BACKSPACE2]:
if self.input and self.input_cursor > 0:
- self.input = self.input[:self.input_cursor - 1] + self.input[self.input_cursor:]
+ self.input = (
+ self.input[: self.input_cursor - 1]
+ + self.input[self.input_cursor :]
+ )
self.input_cursor -= 1
# Delete a word when alt+backspace is pressed
- elif c == [util.KEY_ESC, util.KEY_BACKSPACE2] or c == [util.KEY_ESC, curses.KEY_BACKSPACE]:
- self.input, self.input_cursor = delete_alt_backspace(self.input, self.input_cursor)
+ elif c == [util.KEY_ESC, util.KEY_BACKSPACE2] or c == [
+ util.KEY_ESC,
+ curses.KEY_BACKSPACE,
+ ]:
+ self.input, self.input_cursor = delete_alt_backspace(
+ self.input, self.input_cursor
+ )
elif c == curses.KEY_DC:
if self.input and self.input_cursor < len(self.input):
- self.input = self.input[:self.input_cursor] + self.input[self.input_cursor + 1:]
+ self.input = (
+ self.input[: self.input_cursor]
+ + self.input[self.input_cursor + 1 :]
+ )
# A key to add to the input string
else:
@@ -328,7 +347,11 @@ class CmdLine(BaseMode, Commander):
self.input += uchar
else:
# Insert into string
- self.input = self.input[:self.input_cursor] + uchar + self.input[self.input_cursor:]
+ self.input = (
+ self.input[: self.input_cursor]
+ + uchar
+ + self.input[self.input_cursor :]
+ )
# Move the cursor forward
self.input_cursor += 1
@@ -363,7 +386,7 @@ class CmdLine(BaseMode, Commander):
if len(self.lines) > available_lines:
# Get the lines to display based on the offset
offset = len(self.lines) - self.display_lines_offset
- lines = self.lines[-(available_lines - offset):offset]
+ lines = self.lines[-(available_lines - offset) : offset]
elif len(self.lines) == available_lines:
lines = self.lines
else:
@@ -411,7 +434,10 @@ class CmdLine(BaseMode, Commander):
if self.console_config['cmdline']['save_command_history']:
# Determine which file is the active one
# If both are under maximum, it's first, otherwise it's the one not full
- if self._hf_lines[0] < MAX_HISTFILE_SIZE and self._hf_lines[1] < MAX_HISTFILE_SIZE:
+ if (
+ self._hf_lines[0] < MAX_HISTFILE_SIZE
+ and self._hf_lines[1] < MAX_HISTFILE_SIZE
+ ):
active_file = 0
elif self._hf_lines[0] == MAX_HISTFILE_SIZE:
active_file = 1
@@ -429,7 +455,9 @@ class CmdLine(BaseMode, Commander):
# therefore swapping the currently active file
if self._hf_lines[active_file] == MAX_HISTFILE_SIZE:
self._hf_lines[1 - active_file] = 0
- with open(self.history_file[1 - active_file], 'w', encoding='utf8') as _file:
+ with open(
+ self.history_file[1 - active_file], 'w', encoding='utf8'
+ ) as _file:
_file.truncate(0)
def get_line_chunks(line):
@@ -454,7 +482,7 @@ class CmdLine(BaseMode, Commander):
next_color = line.find('{!', end_color)
if next_color == -1:
next_color = len(line)
- chunks.append((line[:end_color + 2], line[end_color + 2:next_color]))
+ chunks.append((line[: end_color + 2], line[end_color + 2 : next_color]))
line = line[next_color:]
return chunks
@@ -612,7 +640,9 @@ class CmdLine(BaseMode, Commander):
except IndexError:
l_arg = ''
- new_line = ' '.join([p, complete_line(l_arg, possible_matches)]).lstrip()
+ new_line = ' '.join(
+ [p, complete_line(l_arg, possible_matches)]
+ ).lstrip()
if len(remove_formatting(new_line)) > len(line):
line = new_line
@@ -634,7 +664,10 @@ class CmdLine(BaseMode, Commander):
for i in range(listed, listed + max_list):
match = possible_matches[i]
self.write(match.replace(r'\ ', ' '))
- self.write('{!error!}And %i more. Press <tab> to list them' % (left - max_list))
+ self.write(
+ '{!error!}And %i more. Press <tab> to list them'
+ % (left - max_list)
+ )
else:
self.tab_count = 0
for match in possible_matches[listed:]:
@@ -644,22 +677,28 @@ class CmdLine(BaseMode, Commander):
for i in range(listed, listed + max_list):
match = possible_matches[i]
self.write(match.replace(r'\ ', ' '))
- self.write('{!error!}And %i more (%i/%i). Press <tab> to view more' % (
- left - max_list, hits - 1, pages,
- ))
+ self.write(
+ '{!error!}And %i more (%i/%i). Press <tab> to view more'
+ % (left - max_list, hits - 1, pages)
+ )
else:
self.tab_count = 0
for match in possible_matches[listed:]:
self.write(match.replace(r'\ ', ' '))
if hits > 2:
- self.write('{!green!}Finished listing %i torrents (%i/%i)' % (match_count, hits - 1, pages))
+ self.write(
+ '{!green!}Finished listing %i torrents (%i/%i)'
+ % (match_count, hits - 1, pages)
+ )
# We only want to print eventual colors or other control characters, not return them
line = remove_formatting(line)
cursor = len(line)
return (line, cursor)
- def tab_complete_path(self, line, path_type='file', ext='', sort='name', dirs_first=1):
+ def tab_complete_path(
+ self, line, path_type='file', ext='', sort='name', dirs_first=1
+ ):
self.console = component.get('ConsoleUI')
line = line.replace('\\ ', ' ')
@@ -787,17 +826,23 @@ class CmdLine(BaseMode, Commander):
if not empty and torrent_id.startswith(line):
# Highlight the matching part
text = '{!info!}%s{!input!}%s - "%s"' % (
- torrent_id[:line_len], torrent_id[line_len:], torrent_name,
+ torrent_id[:line_len],
+ torrent_id[line_len:],
+ torrent_name,
)
possible_matches.append(text)
if torrent_name.startswith(line):
text = '{!info!}%s{!input!}%s ({!cyan!}%s{!input!})' % (
- escaped_name[:line_len], escaped_name[line_len:], torrent_id,
+ escaped_name[:line_len],
+ escaped_name[line_len:],
+ torrent_id,
)
possible_matches.append(text)
elif torrent_name.lower().startswith(line.lower()):
text = '{!info!}%s{!input!}%s ({!cyan!}%s{!input!})' % (
- escaped_name[:line_len], escaped_name[line_len:], torrent_id,
+ escaped_name[:line_len],
+ escaped_name[line_len:],
+ torrent_id,
)
possible_matches2.append(text)
diff --git a/deluge/ui/console/modes/connectionmanager.py b/deluge/ui/console/modes/connectionmanager.py
index 000360390..84a3fbc14 100644
--- a/deluge/ui/console/modes/connectionmanager.py
+++ b/deluge/ui/console/modes/connectionmanager.py
@@ -27,7 +27,6 @@ log = logging.getLogger(__name__)
class ConnectionManager(BaseMode, PopupsHandler):
-
def __init__(self, stdscr, encoding=None):
PopupsHandler.__init__(self)
self.statuses = {}
@@ -41,11 +40,16 @@ class ConnectionManager(BaseMode, PopupsHandler):
selected_index = self.popup.current_selection() if self.popup else None
popup = SelectablePopup(
- self, _('Select Host'), self._host_selected, border_off_west=1, active_wrap=True,
+ self,
+ _('Select Host'),
+ self._host_selected,
+ border_off_west=1,
+ active_wrap=True,
)
popup.add_header(
- "{!white,black,bold!}'Q'=%s, 'a'=%s, 'D'=%s" %
- (_('Quit'), _('Add Host'), _('Delete Host')), space_below=True,
+ "{!white,black,bold!}'Q'=%s, 'a'=%s, 'D'=%s"
+ % (_('Quit'), _('Add Host'), _('Delete Host')),
+ space_below=True,
)
self.push_popup(popup, clear=True)
@@ -57,7 +61,9 @@ class ConnectionManager(BaseMode, PopupsHandler):
state = 'Online'
args.update({'data': self.statuses[host_id], 'foreground': 'green'})
host_str = '%s:%d [%s]' % (hostname, port, state)
- self.popup.add_line(host_id, host_str, selectable=True, use_underline=True, **args)
+ self.popup.add_line(
+ host_id, host_str, selectable=True, use_underline=True, **args
+ )
if selected_index:
self.popup.set_selection(selected_index)
@@ -66,14 +72,17 @@ class ConnectionManager(BaseMode, PopupsHandler):
def update_hosts_status(self):
for host_entry in self.hostlist.get_hosts_info():
+
def on_host_status(status_info):
self.statuses[status_info[0]] = status_info
self.update_select_host_popup()
+
self.hostlist.get_host_status(host_entry[0]).addCallback(on_host_status)
def _on_connected(self, result):
def on_console_start(result):
component.get('ConsoleUI').set_mode('TorrentList')
+
d = component.get('ConsoleUI').start_console()
d.addCallback(on_console_start)
@@ -94,8 +103,10 @@ class ConnectionManager(BaseMode, PopupsHandler):
self.pop_popup()
else:
self.add_host(
- result['hostname']['value'], result['port']['value'],
- result['username']['value'], result['password']['value'],
+ result['hostname']['value'],
+ result['port']['value'],
+ result['username']['value'],
+ result['password']['value'],
)
def add_popup(self):
diff --git a/deluge/ui/console/modes/eventview.py b/deluge/ui/console/modes/eventview.py
index a908058ef..cd3308cf9 100644
--- a/deluge/ui/console/modes/eventview.py
+++ b/deluge/ui/console/modes/eventview.py
@@ -25,7 +25,6 @@ log = logging.getLogger(__name__)
class EventView(BaseMode):
-
def __init__(self, parent_mode, stdscr, encoding=None):
BaseMode.__init__(self, stdscr, encoding)
self.parent_mode = parent_mode
diff --git a/deluge/ui/console/modes/preferences/preference_panes.py b/deluge/ui/console/modes/preferences/preference_panes.py
index fd989fdbd..5781fc117 100644
--- a/deluge/ui/console/modes/preferences/preference_panes.py
+++ b/deluge/ui/console/modes/preferences/preference_panes.py
@@ -23,11 +23,17 @@ log = logging.getLogger(__name__)
class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler):
-
def __init__(self, name, preferences):
PopupsHandler.__init__(self)
self.preferences = preferences
- BaseWindow.__init__(self, '%s' % name, self.pane_width, preferences.height, posy=1, posx=self.pane_x_pos)
+ BaseWindow.__init__(
+ self,
+ '%s' % name,
+ self.pane_width,
+ preferences.height,
+ posy=1,
+ posx=self.pane_x_pos,
+ )
BaseInputPane.__init__(self, preferences, border_off_east=1)
self.name = name
@@ -76,9 +82,15 @@ class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler):
if ipt.has_input():
# Need special cases for in/out ports or proxy since they are tuples or dicts.
if ipt.name == 'listen_ports_to' or ipt.name == 'listen_ports_from':
- conf_dict['listen_ports'] = (self.infrom.get_value(), self.into.get_value())
+ conf_dict['listen_ports'] = (
+ self.infrom.get_value(),
+ self.into.get_value(),
+ )
elif ipt.name == 'out_ports_to' or ipt.name == 'out_ports_from':
- conf_dict['outgoing_ports'] = (self.outfrom.get_value(), self.outto.get_value())
+ conf_dict['outgoing_ports'] = (
+ self.outfrom.get_value(),
+ self.outto.get_value(),
+ )
elif ipt.name == 'listen_interface':
listen_interface = ipt.get_value().strip()
if is_ip(listen_interface) or not listen_interface:
@@ -99,15 +111,23 @@ class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler):
elif ipt.name == 'proxy_port':
conf_dict.setdefault('proxy', {})['port'] = ipt.get_value()
elif ipt.name == 'proxy_hostnames':
- conf_dict.setdefault('proxy', {})['proxy_hostnames'] = ipt.get_value()
+ conf_dict.setdefault('proxy', {})[
+ 'proxy_hostnames'
+ ] = ipt.get_value()
elif ipt.name == 'proxy_peer_connections':
- conf_dict.setdefault('proxy', {})['proxy_peer_connections'] = ipt.get_value()
+ conf_dict.setdefault('proxy', {})[
+ 'proxy_peer_connections'
+ ] = ipt.get_value()
elif ipt.name == 'proxy_tracker_connections':
- conf_dict.setdefault('proxy', {})['proxy_tracker_connections'] = ipt.get_value()
+ conf_dict.setdefault('proxy', {})[
+ 'proxy_tracker_connections'
+ ] = ipt.get_value()
elif ipt.name == 'force_proxy':
conf_dict.setdefault('proxy', {})['force_proxy'] = ipt.get_value()
elif ipt.name == 'anonymous_mode':
- conf_dict.setdefault('proxy', {})['anonymous_mode'] = ipt.get_value()
+ conf_dict.setdefault('proxy', {})[
+ 'anonymous_mode'
+ ] = ipt.get_value()
else:
conf_dict[ipt.name] = ipt.get_value()
@@ -150,7 +170,6 @@ class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler):
class InterfacePane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Interface'), preferences)
@@ -159,7 +178,8 @@ class InterfacePane(BasePreferencePane):
self.add_header(_('General options'))
self.add_checked_input(
- 'ring_bell', _('Ring system bell when a download finishes'),
+ 'ring_bell',
+ _('Ring system bell when a download finishes'),
console_config['ring_bell'],
)
self.add_header('Console UI', space_above=True)
@@ -169,38 +189,44 @@ class InterfacePane(BasePreferencePane):
console_config['torrentview']['separate_complete'],
)
self.add_checked_input(
- 'move_selection', _('Move selection when moving torrents in the queue'),
+ 'move_selection',
+ _('Move selection when moving torrents in the queue'),
console_config['torrentview']['move_selection'],
)
from deluge.ui.translations_util import get_languages
+
langs = get_languages()
langs.insert(0, ('', 'System Default'))
self.add_combo_input(
- 'language', _('Language'),
- langs, default=console_config['language'],
+ 'language', _('Language'), langs, default=console_config['language']
)
self.add_header(_('Command Line Mode'), space_above=True)
self.add_checked_input(
- 'ignore_duplicate_lines', _('Do not store duplicate input in history'),
+ 'ignore_duplicate_lines',
+ _('Do not store duplicate input in history'),
console_config['cmdline']['ignore_duplicate_lines'],
)
self.add_checked_input(
- 'save_command_history', _('Store and load command line history in command line mode'),
+ 'save_command_history',
+ _('Store and load command line history in command line mode'),
console_config['cmdline']['save_command_history'],
)
self.add_header('')
self.add_checked_input(
- 'third_tab_lists_all', _('Third tab lists all remaining torrents in command line mode'),
+ 'third_tab_lists_all',
+ _('Third tab lists all remaining torrents in command line mode'),
console_config['cmdline']['third_tab_lists_all'],
)
self.add_int_spin_input(
- 'torrents_per_tab_press', _('Torrents per tab press'),
- console_config['cmdline']['torrents_per_tab_press'], min_val=5, max_val=10000,
+ 'torrents_per_tab_press',
+ _('Torrents per tab press'),
+ console_config['cmdline']['torrents_per_tab_press'],
+ min_val=5,
+ max_val=10000,
)
class DownloadsPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Downloads'), preferences)
@@ -208,48 +234,69 @@ class DownloadsPane(BasePreferencePane):
def create_pane(self, core_conf, console_config):
self.add_header(_('Folders'))
self.add_text_input(
- 'download_location', '%s:' % _('Download To'), core_conf['download_location'],
- complete=True, activate_input=True, col='+1',
+ 'download_location',
+ '%s:' % _('Download To'),
+ core_conf['download_location'],
+ complete=True,
+ activate_input=True,
+ col='+1',
)
cmptxt = TextInput(
- self.preferences, 'move_completed_path', None, self.move, self.pane_width,
- core_conf['move_completed_path'], False,
+ self.preferences,
+ 'move_completed_path',
+ None,
+ self.move,
+ self.pane_width,
+ core_conf['move_completed_path'],
+ False,
)
self.add_checkedplus_input(
- 'move_completed', '%s:' % _('Move completed to'),
- cmptxt, core_conf['move_completed'],
+ 'move_completed',
+ '%s:' % _('Move completed to'),
+ cmptxt,
+ core_conf['move_completed'],
)
copytxt = TextInput(
- self.preferences, 'torrentfiles_location', None, self.move, self.pane_width,
- core_conf['torrentfiles_location'], False,
+ self.preferences,
+ 'torrentfiles_location',
+ None,
+ self.move,
+ self.pane_width,
+ core_conf['torrentfiles_location'],
+ False,
)
self.add_checkedplus_input(
- 'copy_torrent_file', '%s:' % _('Copy of .torrent files to'), copytxt,
+ 'copy_torrent_file',
+ '%s:' % _('Copy of .torrent files to'),
+ copytxt,
core_conf['copy_torrent_file'],
)
self.add_checked_input(
- 'del_copy_torrent_file', _('Delete copy of torrent file on remove'),
+ 'del_copy_torrent_file',
+ _('Delete copy of torrent file on remove'),
core_conf['del_copy_torrent_file'],
)
self.add_header(_('Options'), space_above=True)
self.add_checked_input(
- 'prioritize_first_last_pieces', ('Prioritize first and last pieces of torrent'),
+ 'prioritize_first_last_pieces',
+ ('Prioritize first and last pieces of torrent'),
core_conf['prioritize_first_last_pieces'],
)
self.add_checked_input(
- 'sequential_download', _('Sequential download'),
+ 'sequential_download',
+ _('Sequential download'),
core_conf['sequential_download'],
)
self.add_checked_input('add_paused', _('Add Paused'), core_conf['add_paused'])
self.add_checked_input(
- 'pre_allocate_storage', _('Pre-Allocate disk space'),
+ 'pre_allocate_storage',
+ _('Pre-Allocate disk space'),
core_conf['pre_allocate_storage'],
)
class NetworkPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Network'), preferences)
@@ -257,36 +304,49 @@ class NetworkPane(BasePreferencePane):
def create_pane(self, core_conf, console_config):
self.add_header(_('Incomming Ports'))
inrand = self.add_checked_input(
- 'random_port', 'Use Random Ports Active Port: %d'
- % self.preferences.active_port,
+ 'random_port',
+ 'Use Random Ports Active Port: %d' % self.preferences.active_port,
core_conf['random_port'],
)
listen_ports = core_conf['listen_ports']
self.infrom = self.add_int_spin_input(
- 'listen_ports_from', ' %s:' % _('From'),
- value=listen_ports[0], min_val=0, max_val=65535,
+ 'listen_ports_from',
+ ' %s:' % _('From'),
+ value=listen_ports[0],
+ min_val=0,
+ max_val=65535,
)
self.infrom.set_depend(inrand, inverse=True)
self.into = self.add_int_spin_input(
- 'listen_ports_to', ' %s:' % _('To'),
- value=listen_ports[1], min_val=0, max_val=65535,
+ 'listen_ports_to',
+ ' %s:' % _('To'),
+ value=listen_ports[1],
+ min_val=0,
+ max_val=65535,
)
self.into.set_depend(inrand, inverse=True)
self.add_header(_('Outgoing Ports'), space_above=True)
outrand = self.add_checked_input(
- 'random_outgoing_ports', _('Use Random Ports'),
+ 'random_outgoing_ports',
+ _('Use Random Ports'),
core_conf['random_outgoing_ports'],
)
out_ports = core_conf['outgoing_ports']
self.outfrom = self.add_int_spin_input(
- 'out_ports_from', ' %s:' % _('From'),
- value=out_ports[0], min_val=0, max_val=65535,
+ 'out_ports_from',
+ ' %s:' % _('From'),
+ value=out_ports[0],
+ min_val=0,
+ max_val=65535,
)
self.outfrom.set_depend(outrand, inverse=True)
self.outto = self.add_int_spin_input(
- 'out_ports_to', ' %s:' % _('To'),
- value=out_ports[1], min_val=0, max_val=65535,
+ 'out_ports_to',
+ ' %s:' % _('To'),
+ value=out_ports[1],
+ min_val=0,
+ max_val=65535,
)
self.outto.set_depend(outrand, inverse=True)
@@ -300,7 +360,9 @@ class NetworkPane(BasePreferencePane):
self.add_header(_('Outgoing Interface'), space_above=True)
self.add_text_input(
'outgoing_interface',
- _('The interface adapter name for outgoing BitTorrent connections. (Leave empty for default.):'),
+ _(
+ 'The interface adapter name for outgoing BitTorrent connections. (Leave empty for default.):'
+ ),
core_conf['outgoing_interface'],
)
@@ -316,21 +378,33 @@ class NetworkPane(BasePreferencePane):
self.add_header(_('Encryption'), space_above=True)
self.add_select_input(
- 'enc_in_policy', '%s:' % _('Inbound'), [_('Forced'), _('Enabled'), _('Disabled')],
- [0, 1, 2], core_conf['enc_in_policy'], active_default=True, col='+1',
+ 'enc_in_policy',
+ '%s:' % _('Inbound'),
+ [_('Forced'), _('Enabled'), _('Disabled')],
+ [0, 1, 2],
+ core_conf['enc_in_policy'],
+ active_default=True,
+ col='+1',
)
self.add_select_input(
- 'enc_out_policy', '%s:' % _('Outbound'), [_('Forced'), _('Enabled'), _('Disabled')],
- [0, 1, 2], core_conf['enc_out_policy'], active_default=True,
+ 'enc_out_policy',
+ '%s:' % _('Outbound'),
+ [_('Forced'), _('Enabled'), _('Disabled')],
+ [0, 1, 2],
+ core_conf['enc_out_policy'],
+ active_default=True,
)
self.add_select_input(
- 'enc_level', '%s:' % _('Level'), [_('Handshake'), _('Full Stream'), _('Either')],
- [0, 1, 2], core_conf['enc_level'], active_default=True,
+ 'enc_level',
+ '%s:' % _('Level'),
+ [_('Handshake'), _('Full Stream'), _('Either')],
+ [0, 1, 2],
+ core_conf['enc_level'],
+ active_default=True,
)
class BandwidthPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Bandwidth'), preferences)
@@ -338,58 +412,89 @@ class BandwidthPane(BasePreferencePane):
def create_pane(self, core_conf, console_config):
self.add_header(_('Global Bandwidth Usage'))
self.add_int_spin_input(
- 'max_connections_global', '%s:' % _('Maximum Connections'),
- core_conf['max_connections_global'], min_val=-1, max_val=9000,
+ 'max_connections_global',
+ '%s:' % _('Maximum Connections'),
+ core_conf['max_connections_global'],
+ min_val=-1,
+ max_val=9000,
)
self.add_int_spin_input(
- 'max_upload_slots_global', '%s:' % _('Maximum Upload Slots'),
- core_conf['max_upload_slots_global'], min_val=-1, max_val=9000,
+ 'max_upload_slots_global',
+ '%s:' % _('Maximum Upload Slots'),
+ core_conf['max_upload_slots_global'],
+ min_val=-1,
+ max_val=9000,
)
self.add_float_spin_input(
- 'max_download_speed', '%s:' % _('Maximum Download Speed (KiB/s)'),
- core_conf['max_download_speed'], min_val=-1.0, max_val=60000.0,
+ 'max_download_speed',
+ '%s:' % _('Maximum Download Speed (KiB/s)'),
+ core_conf['max_download_speed'],
+ min_val=-1.0,
+ max_val=60000.0,
)
self.add_float_spin_input(
- 'max_upload_speed', '%s:' % _('Maximum Upload Speed (KiB/s)'),
- core_conf['max_upload_speed'], min_val=-1.0, max_val=60000.0,
+ 'max_upload_speed',
+ '%s:' % _('Maximum Upload Speed (KiB/s)'),
+ core_conf['max_upload_speed'],
+ min_val=-1.0,
+ max_val=60000.0,
)
self.add_int_spin_input(
- 'max_half_open_connections', '%s:' % _('Maximum Half-Open Connections'),
- core_conf['max_half_open_connections'], min_val=-1, max_val=9999,
+ 'max_half_open_connections',
+ '%s:' % _('Maximum Half-Open Connections'),
+ core_conf['max_half_open_connections'],
+ min_val=-1,
+ max_val=9999,
)
self.add_int_spin_input(
- 'max_connections_per_second', '%s:' % _('Maximum Connection Attempts per Second'),
- core_conf['max_connections_per_second'], min_val=-1, max_val=9999,
+ 'max_connections_per_second',
+ '%s:' % _('Maximum Connection Attempts per Second'),
+ core_conf['max_connections_per_second'],
+ min_val=-1,
+ max_val=9999,
)
self.add_checked_input(
- 'ignore_limits_on_local_network', _('Ignore limits on local network'),
+ 'ignore_limits_on_local_network',
+ _('Ignore limits on local network'),
core_conf['ignore_limits_on_local_network'],
)
self.add_checked_input(
- 'rate_limit_ip_overhead', _('Rate Limit IP Overhead'),
+ 'rate_limit_ip_overhead',
+ _('Rate Limit IP Overhead'),
core_conf['rate_limit_ip_overhead'],
)
self.add_header(_('Per Torrent Bandwidth Usage'), space_above=True)
self.add_int_spin_input(
- 'max_connections_per_torrent', '%s:' % _('Maximum Connections'),
- core_conf['max_connections_per_torrent'], min_val=-1, max_val=9000,
+ 'max_connections_per_torrent',
+ '%s:' % _('Maximum Connections'),
+ core_conf['max_connections_per_torrent'],
+ min_val=-1,
+ max_val=9000,
)
self.add_int_spin_input(
- 'max_upload_slots_per_torrent', '%s:' % _('Maximum Upload Slots'),
- core_conf['max_upload_slots_per_torrent'], min_val=-1, max_val=9000,
+ 'max_upload_slots_per_torrent',
+ '%s:' % _('Maximum Upload Slots'),
+ core_conf['max_upload_slots_per_torrent'],
+ min_val=-1,
+ max_val=9000,
)
self.add_float_spin_input(
- 'max_download_speed_per_torrent', '%s:' % _('Maximum Download Speed (KiB/s)'),
- core_conf['max_download_speed_per_torrent'], min_val=-1.0, max_val=60000.0,
+ 'max_download_speed_per_torrent',
+ '%s:' % _('Maximum Download Speed (KiB/s)'),
+ core_conf['max_download_speed_per_torrent'],
+ min_val=-1.0,
+ max_val=60000.0,
)
self.add_float_spin_input(
- 'max_upload_speed_per_torrent', '%s:' % _('Maximum Upload Speed (KiB/s)'),
- core_conf['max_upload_speed_per_torrent'], min_val=-1.0, max_val=60000.0,
+ 'max_upload_speed_per_torrent',
+ '%s:' % _('Maximum Upload Speed (KiB/s)'),
+ core_conf['max_upload_speed_per_torrent'],
+ min_val=-1.0,
+ max_val=60000.0,
)
class OtherPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Other'), preferences)
@@ -397,15 +502,24 @@ class OtherPane(BasePreferencePane):
def create_pane(self, core_conf, console_config):
self.add_header(_('System Information'))
self.add_info_field('info1', ' Help us improve Deluge by sending us your', '')
- self.add_info_field('info2', ' Python version, PyGTK version, OS and processor', '')
- self.add_info_field('info3', ' types. Absolutely no other information is sent.', '')
- self.add_checked_input('send_info', _('Yes, please send anonymous statistics.'), core_conf['send_info'])
+ self.add_info_field(
+ 'info2', ' Python version, PyGTK version, OS and processor', ''
+ )
+ self.add_info_field(
+ 'info3', ' types. Absolutely no other information is sent.', ''
+ )
+ self.add_checked_input(
+ 'send_info',
+ _('Yes, please send anonymous statistics.'),
+ core_conf['send_info'],
+ )
self.add_header(_('GeoIP Database'), space_above=True)
- self.add_text_input('geoip_db_location', 'Location:', core_conf['geoip_db_location'])
+ self.add_text_input(
+ 'geoip_db_location', 'Location:', core_conf['geoip_db_location']
+ )
class DaemonPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Daemon'), preferences)
@@ -413,77 +527,115 @@ class DaemonPane(BasePreferencePane):
def create_pane(self, core_conf, console_config):
self.add_header('Port')
self.add_int_spin_input(
- 'daemon_port', '%s:' % _('Daemon Port'), core_conf['daemon_port'],
- min_val=0, max_val=65535,
+ 'daemon_port',
+ '%s:' % _('Daemon Port'),
+ core_conf['daemon_port'],
+ min_val=0,
+ max_val=65535,
)
self.add_header('Connections', space_above=True)
- self.add_checked_input('allow_remote', _('Allow remote connections'), core_conf['allow_remote'])
+ self.add_checked_input(
+ 'allow_remote', _('Allow remote connections'), core_conf['allow_remote']
+ )
self.add_header('Other', space_above=True)
self.add_checked_input(
- 'new_release_check', _('Periodically check the website for new releases'),
+ 'new_release_check',
+ _('Periodically check the website for new releases'),
core_conf['new_release_check'],
)
class QueuePane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Queue'), preferences)
@overrides(BasePreferencePane)
def create_pane(self, core_conf, console_config):
self.add_header(_('New Torrents'))
- self.add_checked_input('queue_new_to_top', _('Queue to top'), core_conf['queue_new_to_top'])
+ self.add_checked_input(
+ 'queue_new_to_top', _('Queue to top'), core_conf['queue_new_to_top']
+ )
self.add_header(_('Active Torrents'), True)
self.add_int_spin_input(
- 'max_active_limit', '%s:' % _('Total'), core_conf['max_active_limit'],
- min_val=-1, max_val=9999,
+ 'max_active_limit',
+ '%s:' % _('Total'),
+ core_conf['max_active_limit'],
+ min_val=-1,
+ max_val=9999,
)
self.add_int_spin_input(
- 'max_active_downloading', '%s:' % _('Downloading'),
- core_conf['max_active_downloading'], min_val=-1, max_val=9999,
+ 'max_active_downloading',
+ '%s:' % _('Downloading'),
+ core_conf['max_active_downloading'],
+ min_val=-1,
+ max_val=9999,
)
self.add_int_spin_input(
- 'max_active_seeding', '%s:' % _('Seeding'),
- core_conf['max_active_seeding'], min_val=-1, max_val=9999,
+ 'max_active_seeding',
+ '%s:' % _('Seeding'),
+ core_conf['max_active_seeding'],
+ min_val=-1,
+ max_val=9999,
)
self.add_checked_input(
- 'dont_count_slow_torrents', 'Ignore slow torrents',
+ 'dont_count_slow_torrents',
+ 'Ignore slow torrents',
core_conf['dont_count_slow_torrents'],
)
self.add_checked_input(
- 'auto_manage_prefer_seeds', 'Prefer seeding torrents',
+ 'auto_manage_prefer_seeds',
+ 'Prefer seeding torrents',
core_conf['auto_manage_prefer_seeds'],
)
self.add_header(_('Seeding Rotation'), space_above=True)
self.add_float_spin_input(
- 'share_ratio_limit', '%s:' % _('Share Ratio'),
- core_conf['share_ratio_limit'], precision=2, min_val=-1.0, max_val=100.0,
+ 'share_ratio_limit',
+ '%s:' % _('Share Ratio'),
+ core_conf['share_ratio_limit'],
+ precision=2,
+ min_val=-1.0,
+ max_val=100.0,
)
self.add_float_spin_input(
- 'seed_time_ratio_limit', '%s:' % _('Time Ratio'),
- core_conf['seed_time_ratio_limit'], precision=2, min_val=-1.0, max_val=100.0,
+ 'seed_time_ratio_limit',
+ '%s:' % _('Time Ratio'),
+ core_conf['seed_time_ratio_limit'],
+ precision=2,
+ min_val=-1.0,
+ max_val=100.0,
)
self.add_int_spin_input(
- 'seed_time_limit', '%s:' % _('Time (m)'), core_conf['seed_time_limit'],
- min_val=1, max_val=10000,
+ 'seed_time_limit',
+ '%s:' % _('Time (m)'),
+ core_conf['seed_time_limit'],
+ min_val=1,
+ max_val=10000,
)
seedratio = FloatSpinInput(
- self.mode, 'stop_seed_ratio', '', self.move, core_conf['stop_seed_ratio'],
- precision=2, inc_amt=0.1, min_val=0.5, max_val=100.0,
+ self.mode,
+ 'stop_seed_ratio',
+ '',
+ self.move,
+ core_conf['stop_seed_ratio'],
+ precision=2,
+ inc_amt=0.1,
+ min_val=0.5,
+ max_val=100.0,
)
self.add_checkedplus_input(
- 'stop_seed_at_ratio', '%s:' % _('Share Ratio Reached'), seedratio,
+ 'stop_seed_at_ratio',
+ '%s:' % _('Share Ratio Reached'),
+ seedratio,
core_conf['stop_seed_at_ratio'],
)
self.add_checked_input(
- 'remove_seed_at_ratio', _('Remove torrent (Unchecked pauses torrent)'),
+ 'remove_seed_at_ratio',
+ _('Remove torrent (Unchecked pauses torrent)'),
core_conf['remove_seed_at_ratio'],
)
class ProxyPane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Proxy'), preferences)
@@ -493,17 +645,31 @@ class ProxyPane(BasePreferencePane):
self.add_header(_('Proxy Settings'))
self.add_header(_('Proxy'), space_above=True)
- self.add_int_spin_input('proxy_type', '%s:' % _('Type'), proxy['type'], min_val=0, max_val=5)
+ self.add_int_spin_input(
+ 'proxy_type', '%s:' % _('Type'), proxy['type'], min_val=0, max_val=5
+ )
self.add_text_input('proxy_username', '%s:' % _('Username'), proxy['username'])
self.add_text_input('proxy_password', '%s:' % _('Password'), proxy['password'])
self.add_text_input('proxy_hostname', '%s:' % _('Hostname'), proxy['hostname'])
- self.add_int_spin_input('proxy_port', '%s:' % _('Port'), proxy['port'], min_val=0, max_val=65535)
- self.add_checked_input('proxy_hostnames', _('Proxy Hostnames'), proxy['proxy_hostnames'])
- self.add_checked_input('proxy_peer_connections', _('Proxy Peers'), proxy['proxy_peer_connections'])
- self.add_checked_input('proxy_tracker_connections', _('Proxy Trackers'), proxy['proxy_tracker_connections'])
+ self.add_int_spin_input(
+ 'proxy_port', '%s:' % _('Port'), proxy['port'], min_val=0, max_val=65535
+ )
+ self.add_checked_input(
+ 'proxy_hostnames', _('Proxy Hostnames'), proxy['proxy_hostnames']
+ )
+ self.add_checked_input(
+ 'proxy_peer_connections', _('Proxy Peers'), proxy['proxy_peer_connections']
+ )
+ self.add_checked_input(
+ 'proxy_tracker_connections',
+ _('Proxy Trackers'),
+ proxy['proxy_tracker_connections'],
+ )
self.add_header('%s' % _('Force Proxy'), space_above=True)
self.add_checked_input('force_proxy', _('Force Proxy'), proxy['force_proxy'])
- self.add_checked_input('anonymous_mode', _('Hide Client Identity'), proxy['anonymous_mode'])
+ self.add_checked_input(
+ 'anonymous_mode', _('Hide Client Identity'), proxy['anonymous_mode']
+ )
self.add_header('%s' % _('Proxy Type Help'), space_above=True)
self.add_text_area(
'proxy_text_area',
@@ -515,7 +681,6 @@ class ProxyPane(BasePreferencePane):
class CachePane(BasePreferencePane):
-
def __init__(self, preferences):
BasePreferencePane.__init__(self, ' %s ' % _('Cache'), preferences)
self.created = False
@@ -529,52 +694,65 @@ class CachePane(BasePreferencePane):
self.add_header(_('Settings'), space_below=True)
self.add_int_spin_input(
'cache_size',
- '%s:' % _('Cache Size (16 KiB blocks)'), core_conf['cache_size'],
- min_val=0, max_val=99999,
+ '%s:' % _('Cache Size (16 KiB blocks)'),
+ core_conf['cache_size'],
+ min_val=0,
+ max_val=99999,
)
self.add_int_spin_input(
'cache_expiry',
- '%s:' % _('Cache Expiry (seconds)'), core_conf['cache_expiry'],
- min_val=1, max_val=32000,
+ '%s:' % _('Cache Expiry (seconds)'),
+ core_conf['cache_expiry'],
+ min_val=1,
+ max_val=32000,
)
self.add_header(' %s' % _('Write'), space_above=True)
- self.add_info_field('blocks_written', ' %s:' % _('Blocks Written'), status['disk.num_blocks_written'])
- self.add_info_field('writes', ' %s:' % _('Writes'), status['disk.num_write_ops'])
+ self.add_info_field(
+ 'blocks_written',
+ ' %s:' % _('Blocks Written'),
+ status['disk.num_blocks_written'],
+ )
+ self.add_info_field(
+ 'writes', ' %s:' % _('Writes'), status['disk.num_write_ops']
+ )
self.add_info_field(
'write_hit_ratio',
- ' %s:' % _('Write Cache Hit Ratio'), '%.2f' % status['write_hit_ratio'],
+ ' %s:' % _('Write Cache Hit Ratio'),
+ '%.2f' % status['write_hit_ratio'],
)
self.add_header(' %s' % _('Read'))
self.add_info_field(
- 'blocks_read',
- ' %s:' % _('Blocks Read'), status['disk.num_blocks_read'],
+ 'blocks_read', ' %s:' % _('Blocks Read'), status['disk.num_blocks_read']
)
self.add_info_field(
'blocks_read_hit',
- ' %s:' % _('Blocks Read hit'), status['disk.num_blocks_cache_hits'],
- )
- self.add_info_field(
- 'reads',
- ' %s:' % _('Reads'), status['disk.num_read_ops'],
+ ' %s:' % _('Blocks Read hit'),
+ status['disk.num_blocks_cache_hits'],
)
+ self.add_info_field('reads', ' %s:' % _('Reads'), status['disk.num_read_ops'])
self.add_info_field(
'read_hit_ratio',
- ' %s:' % _('Read Cache Hit Ratio'), '%.2f' % status['read_hit_ratio'],
+ ' %s:' % _('Read Cache Hit Ratio'),
+ '%.2f' % status['read_hit_ratio'],
)
self.add_header(' %s' % _('Size'))
self.add_info_field(
'cache_size_info',
- ' %s:' % _('Cache Size'), status['disk.disk_blocks_in_use'],
+ ' %s:' % _('Cache Size'),
+ status['disk.disk_blocks_in_use'],
)
self.add_info_field(
'read_cache_size',
- ' %s:' % _('Read Cache Size'), status['disk.read_cache_blocks'],
+ ' %s:' % _('Read Cache Size'),
+ status['disk.read_cache_blocks'],
)
@overrides(BasePreferencePane)
def update(self, active):
if active:
- client.core.get_session_status(DISK_CACHE_KEYS).addCallback(self.update_cache_status_fields)
+ client.core.get_session_status(DISK_CACHE_KEYS).addCallback(
+ self.update_cache_status_fields
+ )
def update_cache_status_fields(self, status):
if not self.created:
diff --git a/deluge/ui/console/modes/preferences/preferences.py b/deluge/ui/console/modes/preferences/preferences.py
index 00c124cd6..45a39a621 100644
--- a/deluge/ui/console/modes/preferences/preferences.py
+++ b/deluge/ui/console/modes/preferences/preferences.py
@@ -16,9 +16,17 @@ import deluge.component as component
from deluge.decorators import overrides
from deluge.ui.client import client
from deluge.ui.console.modes.basemode import BaseMode
-from deluge.ui.console.modes.preferences.preference_panes import (BandwidthPane, CachePane, DaemonPane, DownloadsPane,
- InterfacePane, NetworkPane, OtherPane, ProxyPane,
- QueuePane)
+from deluge.ui.console.modes.preferences.preference_panes import (
+ BandwidthPane,
+ CachePane,
+ DaemonPane,
+ DownloadsPane,
+ InterfacePane,
+ NetworkPane,
+ OtherPane,
+ ProxyPane,
+ QueuePane,
+)
from deluge.ui.console.utils import curses_util as util
from deluge.ui.console.widgets.fields import SelectInput
from deluge.ui.console.widgets.popup import MessagePopup, PopupsHandler
@@ -72,17 +80,28 @@ class ZONE(object):
class PreferenceSidebar(Sidebar):
-
def __init__(self, torrentview, width):
height = curses.LINES - 2
- Sidebar.__init__(self, torrentview, width, height, title=None, border_off_north=1)
+ Sidebar.__init__(
+ self, torrentview, width, height, title=None, border_off_north=1
+ )
self.categories = [
- _('Interface'), _('Downloads'), _('Network'), _('Bandwidth'),
- _('Other'), _('Daemon'), _('Queue'), _('Proxy'), _('Cache'),
+ _('Interface'),
+ _('Downloads'),
+ _('Network'),
+ _('Bandwidth'),
+ _('Other'),
+ _('Daemon'),
+ _('Queue'),
+ _('Proxy'),
+ _('Cache'),
]
for name in self.categories:
self.add_text_field(
- name, name, selectable=True, font_unfocused_active='bold',
+ name,
+ name,
+ selectable=True,
+ font_unfocused_active='bold',
color_unfocused_active='white,black',
)
@@ -91,7 +110,6 @@ class PreferenceSidebar(Sidebar):
class Preferences(BaseMode, PopupsHandler):
-
def __init__(self, parent_mode, stdscr, console_config, encoding=None):
BaseMode.__init__(self, stdscr, encoding=encoding, do_refresh=False)
PopupsHandler.__init__(self)
@@ -123,7 +141,9 @@ class Preferences(BaseMode, PopupsHandler):
CachePane(self),
]
- self.action_input = SelectInput(self, None, None, [_('Cancel'), _('Apply'), _('OK')], [0, 1, 2], 0)
+ self.action_input = SelectInput(
+ self, None, None, [_('Cancel'), _('Apply'), _('OK')], [0, 1, 2], 0
+ )
def load_config(self):
if self.config_loaded:
@@ -135,10 +155,12 @@ class Preferences(BaseMode, PopupsHandler):
for p in self.panes:
p.create_pane(core_config, self.console_config)
self.refresh()
+
client.core.get_config().addCallback(on_get_config)
def on_get_listen_port(port):
self.active_port = port
+
client.core.get_listen_port().addCallback(on_get_listen_port)
@property
@@ -161,15 +183,21 @@ class Preferences(BaseMode, PopupsHandler):
def _draw_preferences(self):
self.cur_cat = self.sidebar.active_input
- self.panes[self.cur_cat].render(self, self.stdscr, self.prefs_width, self.active_zone == ZONE.PREFRENCES)
+ self.panes[self.cur_cat].render(
+ self, self.stdscr, self.prefs_width, self.active_zone == ZONE.PREFRENCES
+ )
self.panes[self.cur_cat].refresh()
def _draw_actions(self):
selected = self.active_zone == ZONE.ACTIONS
self.stdscr.hline(self.rows - 3, self.sidebar_width, b'_', self.cols)
self.action_input.render(
- self.stdscr, self.rows - 2, width=self.cols,
- active=selected, focus=True, col=self.cols - 22,
+ self.stdscr,
+ self.rows - 2,
+ width=self.cols,
+ active=selected,
+ focus=True,
+ col=self.cols - 22,
)
@overrides(BaseMode)
@@ -195,7 +223,10 @@ class Preferences(BaseMode, PopupsHandler):
@overrides(BaseMode)
def refresh(self):
- if not component.get('ConsoleUI').is_active_mode(self) or not self.config_loaded:
+ if (
+ not component.get('ConsoleUI').is_active_mode(self)
+ or not self.config_loaded
+ ):
return
if self.popup is None and self.messages:
@@ -257,14 +288,25 @@ class Preferences(BaseMode, PopupsHandler):
if isinstance(pane, InterfacePane):
pane.add_config_values(new_console_config)
for k in ['ring_bell', 'language']:
- didupdate = update_conf_value(k, new_console_config, self.console_config, didupdate)
+ didupdate = update_conf_value(
+ k, new_console_config, self.console_config, didupdate
+ )
for k in ['separate_complete', 'move_selection']:
- didupdate = update_conf_value(k, new_console_config, self.console_config['torrentview'], didupdate)
+ didupdate = update_conf_value(
+ k,
+ new_console_config,
+ self.console_config['torrentview'],
+ didupdate,
+ )
for k in [
- 'ignore_duplicate_lines', 'save_command_history',
- 'third_tab_lists_all', 'torrents_per_tab_press',
+ 'ignore_duplicate_lines',
+ 'save_command_history',
+ 'third_tab_lists_all',
+ 'torrents_per_tab_press',
]:
- didupdate = update_conf_value(k, new_console_config, self.console_config['cmdline'], didupdate)
+ didupdate = update_conf_value(
+ k, new_console_config, self.console_config['cmdline'], didupdate
+ )
if didupdate:
self.parent_mode.on_config_changed()
diff --git a/deluge/ui/console/modes/torrentdetail.py b/deluge/ui/console/modes/torrentdetail.py
index 9316585ad..cbe3d16c9 100644
--- a/deluge/ui/console/modes/torrentdetail.py
+++ b/deluge/ui/console/modes/torrentdetail.py
@@ -17,12 +17,24 @@ from deluge.decorators import overrides
from deluge.ui.client import client
from deluge.ui.common import FILE_PRIORITY
from deluge.ui.console.modes.basemode import BaseMode
-from deluge.ui.console.modes.torrentlist.torrentactions import ACTION, torrent_actions_popup
+from deluge.ui.console.modes.torrentlist.torrentactions import (
+ ACTION,
+ torrent_actions_popup,
+)
from deluge.ui.console.utils import colors
from deluge.ui.console.utils import curses_util as util
from deluge.ui.console.utils.column import get_column_value, torrent_data_fields
-from deluge.ui.console.utils.format_utils import format_priority, format_progress, format_row
-from deluge.ui.console.widgets.popup import InputPopup, MessagePopup, PopupsHandler, SelectablePopup
+from deluge.ui.console.utils.format_utils import (
+ format_priority,
+ format_progress,
+ format_row,
+)
+from deluge.ui.console.widgets.popup import (
+ InputPopup,
+ MessagePopup,
+ PopupsHandler,
+ SelectablePopup,
+)
try:
import curses
@@ -66,7 +78,6 @@ download priority of selected files and folders.
class TorrentDetail(BaseMode, PopupsHandler):
-
def __init__(self, parent_mode, stdscr, console_config, encoding=None):
PopupsHandler.__init__(self)
self.console_config = console_config
@@ -74,13 +85,37 @@ class TorrentDetail(BaseMode, PopupsHandler):
self.torrentid = None
self.torrent_state = None
self._status_keys = [
- 'files', 'name', 'state', 'download_payload_rate', 'upload_payload_rate',
- 'progress', 'eta', 'all_time_download', 'total_uploaded', 'ratio',
- 'num_seeds', 'total_seeds', 'num_peers', 'total_peers', 'active_time',
- 'seeding_time', 'time_added', 'distributed_copies', 'num_pieces',
- 'piece_length', 'download_location', 'file_progress', 'file_priorities', 'message',
- 'total_wanted', 'tracker_host', 'owner', 'seed_rank', 'last_seen_complete',
- 'completed_time', 'time_since_transfer',
+ 'files',
+ 'name',
+ 'state',
+ 'download_payload_rate',
+ 'upload_payload_rate',
+ 'progress',
+ 'eta',
+ 'all_time_download',
+ 'total_uploaded',
+ 'ratio',
+ 'num_seeds',
+ 'total_seeds',
+ 'num_peers',
+ 'total_peers',
+ 'active_time',
+ 'seeding_time',
+ 'time_added',
+ 'distributed_copies',
+ 'num_pieces',
+ 'piece_length',
+ 'download_location',
+ 'file_progress',
+ 'file_priorities',
+ 'message',
+ 'total_wanted',
+ 'tracker_host',
+ 'owner',
+ 'seed_rank',
+ 'last_seen_complete',
+ 'completed_time',
+ 'time_since_transfer',
]
self.file_list = None
self.current_file = None
@@ -99,9 +134,15 @@ class TorrentDetail(BaseMode, PopupsHandler):
self._listing_start = self.rows // 2
self._listing_space = self._listing_start - self._listing_start
- client.register_event_handler('TorrentFileRenamedEvent', self._on_torrentfilerenamed_event)
- client.register_event_handler('TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event)
- client.register_event_handler('TorrentRemovedEvent', self._on_torrentremoved_event)
+ client.register_event_handler(
+ 'TorrentFileRenamedEvent', self._on_torrentfilerenamed_event
+ )
+ client.register_event_handler(
+ 'TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event
+ )
+ client.register_event_handler(
+ 'TorrentRemovedEvent', self._on_torrentremoved_event
+ )
util.safe_curs_set(util.Curser.INVISIBLE)
self.stdscr.notimeout(0)
@@ -124,8 +165,7 @@ class TorrentDetail(BaseMode, PopupsHandler):
if self.torrentid:
component.get('SessionProxy').get_torrent_status(
- self.torrentid,
- self._status_keys,
+ self.torrentid, self._status_keys
).addCallback(self.set_state)
@overrides(BaseMode)
@@ -152,14 +192,17 @@ class TorrentDetail(BaseMode, PopupsHandler):
# don't keep getting the files once we've got them once
if state.get('files'):
self.files_sep = '{!green,black,bold,underline!}%s' % (
- ('Files (torrent has %d files)' % len(state['files'])).center(self.cols)
+ ('Files (torrent has %d files)' % len(state['files'])).center(
+ self.cols
+ )
)
self.file_list, self.file_dict = self.build_file_list(
- state['files'], state['file_progress'],
- state['file_priorities'],
+ state['files'], state['file_progress'], state['file_priorities']
)
else:
- self.files_sep = '{!green,black,bold,underline!}%s' % (('Files (File list unknown)').center(self.cols))
+ self.files_sep = '{!green,black,bold,underline!}%s' % (
+ ('Files (File list unknown)').center(self.cols)
+ )
need_prio_update = True
self.__fill_progress(self.file_list, state['file_progress'])
@@ -199,10 +242,17 @@ class TorrentDetail(BaseMode, PopupsHandler):
if not cur or path != cur[-1][0]:
child_list = []
if path == paths[-1]:
- file_progress = format_progress(progress[torrent_file['index']] * 100)
+ file_progress = format_progress(
+ progress[torrent_file['index']] * 100
+ )
entry = [
- path, torrent_file['index'], torrent_file['size'], child_list,
- False, file_progress, priority[torrent_file['index']],
+ path,
+ torrent_file['index'],
+ torrent_file['size'],
+ child_list,
+ False,
+ file_progress,
+ priority[torrent_file['index']],
]
file_dict[torrent_file['index']] = entry
else:
@@ -265,18 +315,26 @@ class TorrentDetail(BaseMode, PopupsHandler):
self.column_widths[i] = cw
else:
rem = self.cols - req
- var_cols = len([col_width for col_width in self.column_widths if col_width < 0])
+ var_cols = len(
+ [col_width for col_width in self.column_widths if col_width < 0]
+ )
vw = rem // var_cols
for i in range(0, len(self.column_widths)):
if self.column_widths[i] < 0:
self.column_widths[i] = vw
self.column_string = '{!green,black,bold!}%s' % (
- ''.join(['%s%s' % (
- self.column_names[i], ' ' * (
- self.column_widths[i] - len(self.column_names[i])
- ),
- ) for i in range(0, len(self.column_names))]))
+ ''.join(
+ [
+ '%s%s'
+ % (
+ self.column_names[i],
+ ' ' * (self.column_widths[i] - len(self.column_names[i])),
+ )
+ for i in range(0, len(self.column_names))
+ ]
+ )
+ )
def _on_torrentremoved_event(self, torrent_id):
if torrent_id == self.torrentid:
@@ -286,7 +344,7 @@ class TorrentDetail(BaseMode, PopupsHandler):
if torrent_id == self.torrentid:
self.file_dict[index][0] = new_name.split('/')[-1]
component.get('SessionProxy').get_torrent_status(
- self.torrentid, self._status_keys,
+ self.torrentid, self._status_keys
).addCallback(self.set_state)
def _on_torrentfolderrenamed_event(self, torrent_id, old_folder, new_folder):
@@ -303,7 +361,7 @@ class TorrentDetail(BaseMode, PopupsHandler):
# self.__get_file_by_name(old_folder, self.file_list)[0] = new_folder.strip('/')
component.get('SessionProxy').get_torrent_status(
- self.torrentid, self._status_keys,
+ self.torrentid, self._status_keys
).addCallback(self.set_state)
def draw_files(self, files, depth, off, idx):
@@ -333,7 +391,7 @@ class TorrentDetail(BaseMode, PopupsHandler):
4: 'white', # Normal
5: 'green',
6: 'green',
- 7: 'green', # High
+ 7: 'green', # High
}
fg = priority_fg_color[fl[6]]
@@ -344,7 +402,9 @@ class TorrentDetail(BaseMode, PopupsHandler):
if fl[1] in self.marked:
bg = color_selected
if fl[3]:
- if self.marked[fl[1]] < self.__get_contained_files_count(file_list=fl[3]):
+ if self.marked[fl[1]] < self.__get_contained_files_count(
+ file_list=fl[3]
+ ):
bg = color_partially_selected
attr = 'bold'
@@ -354,7 +414,9 @@ class TorrentDetail(BaseMode, PopupsHandler):
if fl[1] in self.marked:
fg = color_selected
if fl[3]:
- if self.marked[fl[1]] < self.__get_contained_files_count(file_list=fl[3]):
+ if self.marked[fl[1]] < self.__get_contained_files_count(
+ file_list=fl[3]
+ ):
fg = color_partially_selected
else:
if fg == 'white':
@@ -377,7 +439,8 @@ class TorrentDetail(BaseMode, PopupsHandler):
r = format_row(
[
'%s%s %s' % (' ' * depth, xchar, fl[0]),
- fsize(fl[2]), fl[5],
+ fsize(fl[2]),
+ fl[5],
format_priority(fl[6]),
],
self.column_widths,
@@ -439,8 +502,10 @@ class TorrentDetail(BaseMode, PopupsHandler):
def add_field(name, row, pre_color='{!info!}', post_color='{!input!}'):
s = '%s%s: %s%s' % (
- pre_color, torrent_data_fields[name]['name'],
- post_color, get_column_value(name, status),
+ pre_color,
+ torrent_data_fields[name]['name'],
+ post_color,
+ get_column_value(name, status),
)
if row:
row = self.add_string(row, s)
@@ -457,7 +522,10 @@ class TorrentDetail(BaseMode, PopupsHandler):
if status['progress'] != 100.0:
s += '/%s' % fsize(status['total_wanted'])
if status['download_payload_rate'] > 0:
- s += ' {!yellow!}@ %s%s' % (download_color, fsize(status['download_payload_rate']))
+ s += ' {!yellow!}@ %s%s' % (
+ download_color,
+ fsize(status['download_payload_rate']),
+ )
s += add_field('eta', 0)
if s:
row = self.add_string(row, s)
@@ -465,35 +533,48 @@ class TorrentDetail(BaseMode, PopupsHandler):
# Print UL info and ratio
s = add_field('uploaded', 0, download_color)
if status['upload_payload_rate'] > 0:
- s += ' {!yellow!}@ %s%s' % (colors.state_color['Seeding'], fsize(status['upload_payload_rate']))
+ s += ' {!yellow!}@ %s%s' % (
+ colors.state_color['Seeding'],
+ fsize(status['upload_payload_rate']),
+ )
s += ' ' + add_field('ratio', 0)
row = self.add_string(row, s)
# Seed/peer info
s = '{!info!}%s:{!green!} %s {!input!}(%s)' % (
torrent_data_fields['seeds']['name'],
- status['num_seeds'], status['total_seeds'],
+ status['num_seeds'],
+ status['total_seeds'],
)
row = self.add_string(row, s)
s = '{!info!}%s:{!red!} %s {!input!}(%s)' % (
torrent_data_fields['peers']['name'],
- status['num_peers'], status['total_peers'],
+ status['num_peers'],
+ status['total_peers'],
)
row = self.add_string(row, s)
# Tracker
tracker_color = '{!green!}' if status['message'] == 'OK' else '{!red!}'
s = '{!info!}%s: {!magenta!}%s{!input!} says "%s%s{!input!}"' % (
- torrent_data_fields['tracker']['name'], status['tracker_host'], tracker_color, status['message'],
+ torrent_data_fields['tracker']['name'],
+ status['tracker_host'],
+ tracker_color,
+ status['message'],
)
row = self.add_string(row, s)
# Pieces and availability
s = '{!info!}%s: {!yellow!}%s {!input!}x {!yellow!}%s' % (
- torrent_data_fields['pieces']['name'], status['num_pieces'], fsize(status['piece_length']),
+ torrent_data_fields['pieces']['name'],
+ status['num_pieces'],
+ fsize(status['piece_length']),
)
if status['distributed_copies']:
- s += '{!info!}%s: {!input!}%s' % (torrent_data_fields['seed_rank']['name'], status['seed_rank'])
+ s += '{!info!}%s: {!input!}%s' % (
+ torrent_data_fields['seed_rank']['name'],
+ status['seed_rank'],
+ )
row = self.add_string(row, s)
# Time added
@@ -599,7 +680,9 @@ class TorrentDetail(BaseMode, PopupsHandler):
self.build_prio_list(self.file_list, plist, -1, data)
plist.sort()
priorities = [p[1] for p in plist]
- client.core.set_torrent_options([self.torrent_id], {'file_priorities': priorities})
+ client.core.set_torrent_options(
+ [self.torrent_id], {'file_priorities': priorities}
+ )
if was_empty:
self.marked = {}
@@ -607,29 +690,37 @@ class TorrentDetail(BaseMode, PopupsHandler):
# show popup for priority selections
def show_priority_popup(self, was_empty):
-
def popup_func(data, *args, **kwargs):
if data is None:
return
return self.do_priority(data, kwargs[data], was_empty)
if self.marked:
- popup = SelectablePopup(self, 'Set File Priority', popup_func, border_off_north=1)
+ popup = SelectablePopup(
+ self, 'Set File Priority', popup_func, border_off_north=1
+ )
popup.add_line(
- 'ignore_priority', '_Ignore',
- cb_arg=FILE_PRIORITY['Ignore'], foreground='red',
+ 'ignore_priority',
+ '_Ignore',
+ cb_arg=FILE_PRIORITY['Ignore'],
+ foreground='red',
)
popup.add_line(
- 'low_priority', '_Low Priority',
- cb_arg=FILE_PRIORITY['Low Priority'], foreground='yellow',
+ 'low_priority',
+ '_Low Priority',
+ cb_arg=FILE_PRIORITY['Low Priority'],
+ foreground='yellow',
)
popup.add_line(
- 'normal_priority', '_Normal Priority',
+ 'normal_priority',
+ '_Normal Priority',
cb_arg=FILE_PRIORITY['Normal Priority'],
)
popup.add_line(
- 'high_priority', '_High Priority',
- cb_arg=FILE_PRIORITY['High Priority'], foreground='green',
+ 'high_priority',
+ '_High Priority',
+ cb_arg=FILE_PRIORITY['High Priority'],
+ foreground='green',
)
popup._selected = 1
self.push_popup(popup)
@@ -758,7 +849,9 @@ class TorrentDetail(BaseMode, PopupsHandler):
# It's a folder
if element[3]:
- i = self._selection_to_file_idx(element[3], idx + 1, true_idx, closed or not element[4])
+ i = self._selection_to_file_idx(
+ element[3], idx + 1, true_idx, closed or not element[4]
+ )
if isinstance(i, tuple):
idx, true_idx = i
if element[4]:
@@ -786,7 +879,9 @@ class TorrentDetail(BaseMode, PopupsHandler):
if num == idx:
return '%s%s/' % (path, element[0])
if element[4]:
- i = self._get_full_folder_path(num, element[3], path + element[0] + '/', idx + 1)
+ i = self._get_full_folder_path(
+ num, element[3], path + element[0] + '/', idx + 1
+ )
if not isinstance(i, int):
return i
idx = i
@@ -819,27 +914,50 @@ class TorrentDetail(BaseMode, PopupsHandler):
if _file[3]:
def do_rename(result, **kwargs):
- if not result or not result['new_foldername']['value'] or kwargs.get('close', False):
+ if (
+ not result
+ or not result['new_foldername']['value']
+ or kwargs.get('close', False)
+ ):
self.popup.close(None, call_cb=False)
return
old_fname = self._get_full_folder_path(self.current_file_idx)
- new_fname = '%s/%s/' % (old_fname.strip('/').rpartition('/')[0], result['new_foldername']['value'])
+ new_fname = '%s/%s/' % (
+ old_fname.strip('/').rpartition('/')[0],
+ result['new_foldername']['value'],
+ )
self._do_rename_folder(tid, old_fname, new_fname)
- popup = InputPopup(self, 'Rename folder (Esc to cancel)', close_cb=do_rename)
- popup.add_text_input('new_foldername', 'Enter new folder name:', old_filename.strip('/'), complete=True)
+ popup = InputPopup(
+ self, 'Rename folder (Esc to cancel)', close_cb=do_rename
+ )
+ popup.add_text_input(
+ 'new_foldername',
+ 'Enter new folder name:',
+ old_filename.strip('/'),
+ complete=True,
+ )
self.push_popup(popup)
else:
def do_rename(result, **kwargs):
- if not result or not result['new_filename']['value'] or kwargs.get('close', False):
+ if (
+ not result
+ or not result['new_filename']['value']
+ or kwargs.get('close', False)
+ ):
self.popup.close(None, call_cb=False)
return
- fname = '%s/%s' % (self.full_names[idx].rpartition('/')[0], result['new_filename']['value'])
+ fname = '%s/%s' % (
+ self.full_names[idx].rpartition('/')[0],
+ result['new_filename']['value'],
+ )
self._do_rename_file(tid, idx, fname)
popup = InputPopup(self, ' Rename file ', close_cb=do_rename)
- popup.add_text_input('new_filename', 'Enter new filename:', old_filename, complete=True)
+ popup.add_text_input(
+ 'new_filename', 'Enter new filename:', old_filename, complete=True
+ )
self.push_popup(popup)
@overrides(BaseMode)
@@ -879,7 +997,7 @@ class TorrentDetail(BaseMode, PopupsHandler):
elif c == curses.KEY_DC:
torrent_actions_popup(self, [self.torrentid], action=ACTION.REMOVE)
elif c in [curses.KEY_ENTER, util.KEY_ENTER2]:
- was_empty = (self.marked == {})
+ was_empty = self.marked == {}
self.__mark_tree(self.file_list, self.current_file[1])
self.show_priority_popup(was_empty)
elif c == util.KEY_SPACE:
diff --git a/deluge/ui/console/modes/torrentlist/__init__.py b/deluge/ui/console/modes/torrentlist/__init__.py
index 9a41a6636..18c4db377 100644
--- a/deluge/ui/console/modes/torrentlist/__init__.py
+++ b/deluge/ui/console/modes/torrentlist/__init__.py
@@ -11,7 +11,7 @@ class ACTION(object):
REMOVE_DATA = 6
REMOVE_NODATA = 7
DETAILS = 'torrent_details'
- MOVE_STORAGE = ('move_download_folder')
+ MOVE_STORAGE = 'move_download_folder'
QUEUE = 'queue'
QUEUE_TOP = 'queue_top'
QUEUE_UP = 'queue_up'
diff --git a/deluge/ui/console/modes/torrentlist/add_torrents_popup.py b/deluge/ui/console/modes/torrentlist/add_torrents_popup.py
index 3cc7ee253..b0ac483a0 100644
--- a/deluge/ui/console/modes/torrentlist/add_torrents_popup.py
+++ b/deluge/ui/console/modes/torrentlist/add_torrents_popup.py
@@ -20,16 +20,19 @@ log = logging.getLogger(__name__)
def report_add_status(torrentlist, succ_cnt, fail_cnt, fail_msgs):
if fail_cnt == 0:
- torrentlist.report_message('Torrents Added', '{!success!}Successfully added %d torrent(s)' % succ_cnt)
+ torrentlist.report_message(
+ 'Torrents Added', '{!success!}Successfully added %d torrent(s)' % succ_cnt
+ )
else:
- msg = ('{!error!}Failed to add the following %d torrent(s):\n {!input!}' % fail_cnt) + '\n '.join(fail_msgs)
+ msg = (
+ '{!error!}Failed to add the following %d torrent(s):\n {!input!}' % fail_cnt
+ ) + '\n '.join(fail_msgs)
if succ_cnt != 0:
msg += '\n \n{!success!}Successfully added %d torrent(s)' % succ_cnt
torrentlist.report_message('Torrent Add Report', msg)
def show_torrent_add_popup(torrentlist):
-
def do_add_from_url(data=None, **kwargs):
torrentlist.pop_popup()
if not data or kwargs.get('close', False):
@@ -51,30 +54,47 @@ def show_torrent_add_popup(torrentlist):
if not url:
return
- t_options = {'download_location': data['path']['value'], 'add_paused': data['add_paused']['value']}
+ t_options = {
+ 'download_location': data['path']['value'],
+ 'add_paused': data['add_paused']['value'],
+ }
if deluge.common.is_magnet(url):
- client.core.add_torrent_magnet(url, t_options).addCallback(success_cb, url).addErrback(fail_cb, url)
+ client.core.add_torrent_magnet(url, t_options).addCallback(
+ success_cb, url
+ ).addErrback(fail_cb, url)
elif deluge.common.is_url(url):
- client.core.add_torrent_url(url, t_options).addCallback(success_cb, url).addErrback(fail_cb, url)
+ client.core.add_torrent_url(url, t_options).addCallback(
+ success_cb, url
+ ).addErrback(fail_cb, url)
else:
- torrentlist.report_message('Error', '{!error!}Invalid URL or magnet link: %s' % url)
+ torrentlist.report_message(
+ 'Error', '{!error!}Invalid URL or magnet link: %s' % url
+ )
return
log.debug(
'Adding Torrent(s): %s (dl path: %s) (paused: %d)',
- url, data['path']['value'], data['add_paused']['value'],
+ url,
+ data['path']['value'],
+ data['add_paused']['value'],
)
def show_add_url_popup():
add_paused = 1 if 'add_paused' in torrentlist.coreconfig else 0
- popup = InputPopup(torrentlist, 'Add Torrent (Esc to cancel)', close_cb=do_add_from_url)
+ popup = InputPopup(
+ torrentlist, 'Add Torrent (Esc to cancel)', close_cb=do_add_from_url
+ )
popup.add_text_input('url', 'Enter torrent URL or Magnet link:')
popup.add_text_input(
- 'path', 'Enter save path:', torrentlist.coreconfig.get('download_location', ''),
+ 'path',
+ 'Enter save path:',
+ torrentlist.coreconfig.get('download_location', ''),
complete=True,
)
- popup.add_select_input('add_paused', 'Add Paused:', ['Yes', 'No'], [True, False], add_paused)
+ popup.add_select_input(
+ 'add_paused', 'Add Paused:', ['Yes', 'No'], [True, False], add_paused
+ )
torrentlist.push_popup(popup)
def option_chosen(selected, *args, **kwargs):
diff --git a/deluge/ui/console/modes/torrentlist/filtersidebar.py b/deluge/ui/console/modes/torrentlist/filtersidebar.py
index 49e26ed89..0f39b5c3c 100644
--- a/deluge/ui/console/modes/torrentlist/filtersidebar.py
+++ b/deluge/ui/console/modes/torrentlist/filtersidebar.py
@@ -29,36 +29,54 @@ class FilterSidebar(Sidebar, Component):
torrents based on state.
"""
+
def __init__(self, torrentlist, config):
self.config = config
height = curses.LINES - 2
width = self.config['torrentview']['sidebar_width']
Sidebar.__init__(
- self, torrentlist, width, height, title=' Filter ', border_off_north=1,
+ self,
+ torrentlist,
+ width,
+ height,
+ title=' Filter ',
+ border_off_north=1,
allow_resize=True,
)
Component.__init__(self, 'FilterSidebar')
self.checked_index = 0
- kwargs = {'checked_char': '*', 'unchecked_char': '-', 'checkbox_format': ' %s ', 'col': 0}
+ kwargs = {
+ 'checked_char': '*',
+ 'unchecked_char': '-',
+ 'checkbox_format': ' %s ',
+ 'col': 0,
+ }
self.add_checked_input('All', 'All', checked=True, **kwargs)
self.add_checked_input('Active', 'Active', **kwargs)
- self.add_checked_input('Downloading', 'Downloading', color='green,black', **kwargs)
+ self.add_checked_input(
+ 'Downloading', 'Downloading', color='green,black', **kwargs
+ )
self.add_checked_input('Seeding', 'Seeding', color='cyan,black', **kwargs)
self.add_checked_input('Paused', 'Paused', **kwargs)
self.add_checked_input('Error', 'Error', color='red,black', **kwargs)
self.add_checked_input('Checking', 'Checking', color='blue,black', **kwargs)
self.add_checked_input('Queued', 'Queued', **kwargs)
- self.add_checked_input('Allocating', 'Allocating', color='yellow,black', **kwargs)
+ self.add_checked_input(
+ 'Allocating', 'Allocating', color='yellow,black', **kwargs
+ )
self.add_checked_input('Moving', 'Moving', color='green,black', **kwargs)
@overrides(Component)
def update(self):
if not self.hidden() and client.connected():
- d = client.core.get_filter_tree(True, []).addCallback(self._cb_update_filter_tree)
+ d = client.core.get_filter_tree(True, []).addCallback(
+ self._cb_update_filter_tree
+ )
def on_filter_tree_updated(changed):
if changed:
self.refresh()
+
d.addCallback(on_filter_tree_updated)
def _cb_update_filter_tree(self, filter_items):
@@ -78,7 +96,11 @@ class FilterSidebar(Sidebar, Component):
for state in states:
field = self.get_input(state[0])
if field:
- txt = ('%%-%ds%%%ds' % (filter_state_width, filter_count_width) % (state[0], state[1]))
+ txt = (
+ '%%-%ds%%%ds'
+ % (filter_state_width, filter_count_width)
+ % (state[0], state[1])
+ )
if field.set_message(txt):
changed = True
return changed
@@ -86,7 +108,9 @@ class FilterSidebar(Sidebar, Component):
@overrides(BaseInputPane)
def immediate_action_cb(self, state_changed=True):
if state_changed:
- self.parent.torrentview.set_torrent_filter(self.inputs[self.active_input].name)
+ self.parent.torrentview.set_torrent_filter(
+ self.inputs[self.active_input].name
+ )
@overrides(Sidebar)
def handle_read(self, c):
diff --git a/deluge/ui/console/modes/torrentlist/queue_mode.py b/deluge/ui/console/modes/torrentlist/queue_mode.py
index 9a98e86c3..0c44aafdf 100644
--- a/deluge/ui/console/modes/torrentlist/queue_mode.py
+++ b/deluge/ui/console/modes/torrentlist/queue_mode.py
@@ -39,14 +39,15 @@ Change queue position of selected torrents
class QueueMode(object):
-
def __init__(self, torrentslist, torrent_ids):
self.torrentslist = torrentslist
self.torrentview = torrentslist.torrentview
self.torrent_ids = torrent_ids
def set_statusbar_args(self, statusbar_args):
- statusbar_args['bottombar'] = '{!black,white!}Queue mode: change queue position of selected torrents.'
+ statusbar_args[
+ 'bottombar'
+ ] = '{!black,white!}Queue mode: change queue position of selected torrents.'
statusbar_args['bottombar_help'] = ' Press [h] for help'
def update_cursor(self):
@@ -59,9 +60,22 @@ class QueueMode(object):
if c in [util.KEY_ESC, util.KEY_BELL]: # If Escape key or CTRL-g, we abort
self.torrentslist.set_minor_mode(None)
elif c == ord('h'):
- popup = MessagePopup(self.torrentslist, 'Help', QUEUE_MODE_HELP_STR, width_req=0.65, border_off_west=1)
+ popup = MessagePopup(
+ self.torrentslist,
+ 'Help',
+ QUEUE_MODE_HELP_STR,
+ width_req=0.65,
+ border_off_west=1,
+ )
self.torrentslist.push_popup(popup, clear=True)
- elif c in [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_HOME, curses.KEY_END, curses.KEY_NPAGE, curses.KEY_PPAGE]:
+ elif c in [
+ curses.KEY_UP,
+ curses.KEY_DOWN,
+ curses.KEY_HOME,
+ curses.KEY_END,
+ curses.KEY_NPAGE,
+ curses.KEY_PPAGE,
+ ]:
action = key_to_action[c]
self.do_queue(action)
@@ -78,38 +92,64 @@ class QueueMode(object):
selected_num += 1
if qact == ACTION.QUEUE_TOP:
if self.torrentview.marked:
- self.torrentview.cursel = 1 + sorted(self.torrentview.marked).index(self.torrentview.cursel)
+ self.torrentview.cursel = 1 + sorted(self.torrentview.marked).index(
+ self.torrentview.cursel
+ )
else:
self.torrentview.cursel = 1
self.torrentview.marked = list(range(1, selected_num + 1))
elif qact == ACTION.QUEUE_UP:
self.torrentview.cursel = max(1, self.torrentview.cursel - 1)
self.torrentview.marked = [marked - 1 for marked in self.torrentview.marked]
- self.torrentview.marked = [marked for marked in self.torrentview.marked if marked > 0]
+ self.torrentview.marked = [
+ marked for marked in self.torrentview.marked if marked > 0
+ ]
elif qact == ACTION.QUEUE_DOWN:
self.torrentview.cursel = min(queue_length, self.torrentview.cursel + 1)
self.torrentview.marked = [marked + 1 for marked in self.torrentview.marked]
- self.torrentview.marked = [marked for marked in self.torrentview.marked if marked <= queue_length]
+ self.torrentview.marked = [
+ marked for marked in self.torrentview.marked if marked <= queue_length
+ ]
elif qact == ACTION.QUEUE_BOTTOM:
if self.torrentview.marked:
- self.torrentview.cursel = (queue_length - selected_num + 1 +
- sorted(self.torrentview.marked).index(self.torrentview.cursel))
+ self.torrentview.cursel = (
+ queue_length
+ - selected_num
+ + 1
+ + sorted(self.torrentview.marked).index(self.torrentview.cursel)
+ )
else:
self.torrentview.cursel = queue_length
- self.torrentview.marked = list(range(queue_length - selected_num + 1, queue_length + 1))
+ self.torrentview.marked = list(
+ range(queue_length - selected_num + 1, queue_length + 1)
+ )
def do_queue(self, qact, *args, **kwargs):
if qact == ACTION.QUEUE_TOP:
- client.core.queue_top(self.torrent_ids).addCallback(self.move_selection, qact)
+ client.core.queue_top(self.torrent_ids).addCallback(
+ self.move_selection, qact
+ )
elif qact == ACTION.QUEUE_BOTTOM:
- client.core.queue_bottom(self.torrent_ids).addCallback(self.move_selection, qact)
+ client.core.queue_bottom(self.torrent_ids).addCallback(
+ self.move_selection, qact
+ )
elif qact == ACTION.QUEUE_UP:
- client.core.queue_up(self.torrent_ids).addCallback(self.move_selection, qact)
+ client.core.queue_up(self.torrent_ids).addCallback(
+ self.move_selection, qact
+ )
elif qact == ACTION.QUEUE_DOWN:
- client.core.queue_down(self.torrent_ids).addCallback(self.move_selection, qact)
+ client.core.queue_down(self.torrent_ids).addCallback(
+ self.move_selection, qact
+ )
def popup(self, **kwargs):
- popup = SelectablePopup(self.torrentslist, 'Queue Action', self.do_queue, cb_args=kwargs, border_off_west=1)
+ popup = SelectablePopup(
+ self.torrentslist,
+ 'Queue Action',
+ self.do_queue,
+ cb_args=kwargs,
+ border_off_west=1,
+ )
popup.add_line(ACTION.QUEUE_TOP, '_Top')
popup.add_line(ACTION.QUEUE_UP, '_Up')
popup.add_line(ACTION.QUEUE_DOWN, '_Down')
diff --git a/deluge/ui/console/modes/torrentlist/search_mode.py b/deluge/ui/console/modes/torrentlist/search_mode.py
index f28bf75cb..6720c925a 100644
--- a/deluge/ui/console/modes/torrentlist/search_mode.py
+++ b/deluge/ui/console/modes/torrentlist/search_mode.py
@@ -41,14 +41,12 @@ SEARCH_FORMAT = {
SEARCH_EMPTY: '{!black,white!}Search torrents: %s{!black,white!}',
SEARCH_SUCCESS: '{!black,white!}Search torrents: {!black,green!}%s{!black,white!}',
SEARCH_FAILING: '{!black,white!}Search torrents: {!black,red!}%s{!black,white!}',
- SEARCH_START_REACHED:
- '{!black,white!}Search torrents: {!black,yellow!}%s{!black,white!} (start reached)',
+ SEARCH_START_REACHED: '{!black,white!}Search torrents: {!black,yellow!}%s{!black,white!} (start reached)',
SEARCH_END_REACHED: '{!black,white!}Search torrents: {!black,yellow!}%s{!black,white!} (end reached)',
}
class SearchMode(InputKeyHandler):
-
def __init__(self, torrentlist):
super(SearchMode, self).__init__()
self.torrentlist = torrentlist
@@ -58,10 +56,16 @@ class SearchMode(InputKeyHandler):
def update_cursor(self):
util.safe_curs_set(util.Curser.VERY_VISIBLE)
- move_cursor(self.torrentlist.stdscr, self.torrentlist.rows - 1, len(self.search_string) + 17)
+ move_cursor(
+ self.torrentlist.stdscr,
+ self.torrentlist.rows - 1,
+ len(self.search_string) + 17,
+ )
def set_statusbar_args(self, statusbar_args):
- statusbar_args['bottombar'] = SEARCH_FORMAT[self.search_state] % self.search_string
+ statusbar_args['bottombar'] = (
+ SEARCH_FORMAT[self.search_state] % self.search_string
+ )
statusbar_args['bottombar_help'] = False
def update_colors(self, tidx, colors):
@@ -92,18 +96,23 @@ class SearchMode(InputKeyHandler):
if direction == 'last':
search_space = reversed(search_space)
elif direction == 'next':
- search_space = search_space[self.torrentview.cursel + 1:]
+ search_space = search_space[self.torrentview.cursel + 1 :]
elif direction == 'previous':
- search_space = reversed(search_space[:self.torrentview.cursel])
+ search_space = reversed(search_space[: self.torrentview.cursel])
search_string = self.search_string.lower()
for i, n in search_space:
n = n.lower()
if n.find(search_string) != -1:
self.torrentview.cursel = i
- if (self.torrentview.curoff + self.torrentview.torrent_rows - self.torrentview.torrentlist_offset)\
- < self.torrentview.cursel:
- self.torrentview.curoff = self.torrentview.cursel - self.torrentview.torrent_rows + 1
+ if (
+ self.torrentview.curoff
+ + self.torrentview.torrent_rows
+ - self.torrentview.torrentlist_offset
+ ) < self.torrentview.cursel:
+ self.torrentview.curoff = (
+ self.torrentview.cursel - self.torrentview.torrent_rows + 1
+ )
elif (self.torrentview.curoff + 1) > self.torrentview.cursel:
self.torrentview.curoff = max(0, self.torrentview.cursel)
self.search_state = SEARCH_SUCCESS
@@ -120,7 +129,10 @@ class SearchMode(InputKeyHandler):
cname = self.torrentview.torrent_names[self.torrentview.cursel]
refresh = True
- if c in [util.KEY_ESC, util.KEY_BELL]: # If Escape key or CTRL-g, we abort search
+ if c in [
+ util.KEY_ESC,
+ util.KEY_BELL,
+ ]: # If Escape key or CTRL-g, we abort search
self.torrentlist.set_minor_mode(None)
self.search_state = SEARCH_EMPTY
elif c in [curses.KEY_BACKSPACE, util.KEY_BACKSPACE2]:
@@ -175,9 +187,9 @@ class SearchMode(InputKeyHandler):
self.search_string += uchar
still_matching = (
- cname.lower().find(self.search_string.lower()) ==
- cname.lower().find(old_search_string.lower()) and
- cname.lower().find(self.search_string.lower()) != -1
+ cname.lower().find(self.search_string.lower())
+ == cname.lower().find(old_search_string.lower())
+ and cname.lower().find(self.search_string.lower()) != -1
)
if self.search_string and not still_matching:
diff --git a/deluge/ui/console/modes/torrentlist/torrentactions.py b/deluge/ui/console/modes/torrentlist/torrentactions.py
index f7376f273..1d49929eb 100644
--- a/deluge/ui/console/modes/torrentlist/torrentactions.py
+++ b/deluge/ui/console/modes/torrentlist/torrentactions.py
@@ -26,9 +26,18 @@ from . import ACTION
log = logging.getLogger(__name__)
torrent_options = [
- 'max_download_speed', 'max_upload_speed', 'max_connections', 'max_upload_slots',
- 'prioritize_first_last', 'sequential_download', 'is_auto_managed', 'stop_at_ratio',
- 'stop_ratio', 'remove_at_ratio', 'move_completed', 'move_completed_path',
+ 'max_download_speed',
+ 'max_upload_speed',
+ 'max_connections',
+ 'max_upload_slots',
+ 'prioritize_first_last',
+ 'sequential_download',
+ 'is_auto_managed',
+ 'stop_at_ratio',
+ 'stop_ratio',
+ 'remove_at_ratio',
+ 'move_completed',
+ 'move_completed_path',
]
@@ -38,7 +47,6 @@ def action_error(error, mode):
def action_remove(mode=None, torrent_ids=None, **kwargs):
-
def do_remove(*args, **kwargs):
data = args[0] if args else None
if data is None or kwargs.get('close', False):
@@ -53,7 +61,9 @@ def action_remove(mode=None, torrent_ids=None, **kwargs):
error_msgs = ''
for t_id, e_msg in errors:
error_msgs += 'Error removing torrent %s : %s\n' % (t_id, e_msg)
- mode.report_message('Error(s) occured when trying to delete torrent(s).', error_msgs)
+ mode.report_message(
+ 'Error(s) occured when trying to delete torrent(s).', error_msgs
+ )
mode.refresh()
d = client.core.remove_torrents(torrent_ids, remove_data)
@@ -73,7 +83,9 @@ def action_remove(mode=None, torrent_ids=None, **kwargs):
if len(torrent_ids) == 1:
rem_msg = '{!info!}Remove the following torrent?{!input!}'
else:
- rem_msg = '{!info!}Remove the following %d torrents?{!input!}' % len(torrent_ids)
+ rem_msg = '{!info!}Remove the following %d torrents?{!input!}' % len(
+ torrent_ids
+ )
show_max = 6
for i, (name, state) in enumerate(status):
@@ -85,16 +97,23 @@ def action_remove(mode=None, torrent_ids=None, **kwargs):
break
popup = InputPopup(
- mode, '(Esc to cancel, Enter to remove)', close_cb=do_remove,
- border_off_west=1, border_off_north=1,
+ mode,
+ '(Esc to cancel, Enter to remove)',
+ close_cb=do_remove,
+ border_off_west=1,
+ border_off_north=1,
)
popup.add_text(rem_msg)
popup.add_spaces(1)
popup.add_select_input(
- 'remove_files', '{!info!}Torrent files:',
- ['Keep', 'Remove'], [False, True], False,
+ 'remove_files',
+ '{!info!}Torrent files:',
+ ['Keep', 'Remove'],
+ [False, True],
+ False,
)
mode.push_popup(popup)
+
defer.DeferredList(callbacks).addCallback(remove_dialog)
@@ -128,9 +147,13 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs):
if kwargs.get('close', False):
mode.pop_popup()
return True
+
option_popup = InputPopup(
- mode, ' Set Torrent Options ', close_cb=cb,
- border_off_west=1, border_off_north=1,
+ mode,
+ ' Set Torrent Options ',
+ close_cb=cb,
+ border_off_west=1,
+ border_off_north=1,
base_popup=kwargs.get('base_popup', None),
)
for field in torrent_options:
@@ -140,9 +163,13 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs):
option_popup.add_text_input(field, caption, value)
elif isinstance(value, bool):
choices = (['Yes', 'No'], [True, False], [True, False].index(value))
- option_popup.add_select_input(field, caption, choices[0], choices[1], choices[2])
+ option_popup.add_select_input(
+ field, caption, choices[0], choices[1], choices[2]
+ )
elif isinstance(value, float):
- option_popup.add_float_spin_input(field, caption, value=value, min_val=-1)
+ option_popup.add_float_spin_input(
+ field, caption, value=value, min_val=-1
+ )
elif isinstance(value, int):
option_popup.add_int_spin_input(field, caption, value=value, min_val=-1)
@@ -150,7 +177,9 @@ def action_torrent_info(mode=None, torrent_ids=None, **kwargs):
callbacks = []
for tid in torrents:
- deferred = component.get('SessionProxy').get_torrent_status(tid, torrent_options)
+ deferred = component.get('SessionProxy').get_torrent_status(
+ tid, torrent_options
+ )
callbacks.append(deferred.addCallback(on_torrent_status))
callbacks = defer.DeferredList(callbacks)
@@ -181,20 +210,28 @@ def torrent_action(action, *args, **kwargs):
action_remove(**kwargs)
return False
elif action == ACTION.MOVE_STORAGE:
+
def do_move(res, **kwargs):
if res is None or kwargs.get('close', False):
mode.pop_popup()
return True
- if os.path.exists(res['path']['value']) and not os.path.isdir(res['path']['value']):
+ if os.path.exists(res['path']['value']) and not os.path.isdir(
+ res['path']['value']
+ ):
mode.report_message(
'Cannot Move Download Folder',
'{!error!}%s exists and is not a directory' % res['path']['value'],
)
else:
log.debug('Moving %s to: %s', torrent_ids, res['path']['value'])
- client.core.move_storage(torrent_ids, res['path']['value']).addErrback(action_error, mode)
- popup = InputPopup(mode, 'Move Download Folder', close_cb=do_move, border_off_east=1)
+ client.core.move_storage(torrent_ids, res['path']['value']).addErrback(
+ action_error, mode
+ )
+
+ popup = InputPopup(
+ mode, 'Move Download Folder', close_cb=do_move, border_off_east=1
+ )
popup.add_text_input('path', 'Enter path to move to:', complete=True)
mode.push_popup(popup)
elif action == ACTION.RECHECK:
@@ -226,10 +263,14 @@ def torrent_actions_popup(mode, torrent_ids, details=False, action=None, close_c
return
popup = SelectablePopup(
- mode, 'Torrent Actions', torrent_action,
+ mode,
+ 'Torrent Actions',
+ torrent_action,
cb_args={'mode': mode, 'torrent_ids': torrent_ids},
- close_cb=close_cb, border_off_north=1,
- border_off_west=1, border_off_east=1,
+ close_cb=close_cb,
+ border_off_north=1,
+ border_off_west=1,
+ border_off_east=1,
)
popup.add_line(ACTION.PAUSE, '_Pause')
popup.add_line(ACTION.RESUME, '_Resume')
diff --git a/deluge/ui/console/modes/torrentlist/torrentlist.py b/deluge/ui/console/modes/torrentlist/torrentlist.py
index 0af01a633..a427d65b0 100644
--- a/deluge/ui/console/modes/torrentlist/torrentlist.py
+++ b/deluge/ui/console/modes/torrentlist/torrentlist.py
@@ -18,7 +18,9 @@ from deluge.decorators import overrides
from deluge.ui.client import client
from deluge.ui.console.modes.basemode import BaseMode, mkwin
from deluge.ui.console.modes.torrentlist import torrentview, torrentviewcolumns
-from deluge.ui.console.modes.torrentlist.add_torrents_popup import show_torrent_add_popup
+from deluge.ui.console.modes.torrentlist.add_torrents_popup import (
+ show_torrent_add_popup,
+)
from deluge.ui.console.modes.torrentlist.filtersidebar import FilterSidebar
from deluge.ui.console.modes.torrentlist.queue_mode import QueueMode
from deluge.ui.console.modes.torrentlist.search_mode import SearchMode
@@ -102,9 +104,10 @@ where you input something
class TorrentList(BaseMode, PopupsHandler):
-
def __init__(self, stdscr, encoding=None):
- BaseMode.__init__(self, stdscr, encoding=encoding, do_refresh=False, depend=['SessionProxy'])
+ BaseMode.__init__(
+ self, stdscr, encoding=encoding, do_refresh=False, depend=['SessionProxy']
+ )
PopupsHandler.__init__(self)
self.messages = deque()
self.last_mark = -1
@@ -116,8 +119,11 @@ class TorrentList(BaseMode, PopupsHandler):
self.config = self.consoleui.config
self.sidebar = FilterSidebar(self, self.config)
self.torrentview_panel = mkwin(
- curses.COLOR_GREEN, curses.LINES - 1,
- curses.COLS - self.sidebar.width, 0, self.sidebar.width,
+ curses.COLOR_GREEN,
+ curses.LINES - 1,
+ curses.COLS - self.sidebar.width,
+ 0,
+ self.sidebar.width,
)
self.torrentview = torrentview.TorrentView(self, self.config)
@@ -135,7 +141,9 @@ class TorrentList(BaseMode, PopupsHandler):
if self.config['torrentview']['show_sidebar']:
self.sidebar.show()
self.sidebar.resize_window(curses.LINES - 2, self.sidebar.width)
- self.torrentview_panel.resize(curses.LINES - 1, curses.COLS - self.sidebar.width)
+ self.torrentview_panel.resize(
+ curses.LINES - 1, curses.COLS - self.sidebar.width
+ )
self.torrentview_panel.mvwin(0, self.sidebar.width)
else:
self.sidebar.hide()
@@ -152,7 +160,9 @@ class TorrentList(BaseMode, PopupsHandler):
self.toggle_sidebar()
if self.config['first_run']:
- self.push_popup(MessagePopup(self, 'Welcome to Deluge', HELP_STR, width_req=0.65))
+ self.push_popup(
+ MessagePopup(self, 'Welcome to Deluge', HELP_STR, width_req=0.65)
+ )
self.config['first_run'] = False
self.config.save()
@@ -212,8 +222,10 @@ class TorrentList(BaseMode, PopupsHandler):
# Update the status bars
statusbar_args = {'scr': self.stdscr, 'bottombar_help': True}
if self.torrentview.curr_filter is not None:
- statusbar_args['topbar'] = ('%s {!filterstatus!}Current filter: %s'
- % (self.statusbars.topbar, self.torrentview.curr_filter))
+ statusbar_args['topbar'] = '%s {!filterstatus!}Current filter: %s' % (
+ self.statusbars.topbar,
+ self.torrentview.curr_filter,
+ )
if self.minor_mode:
self.minor_mode.set_statusbar_args(statusbar_args)
@@ -269,7 +281,9 @@ class TorrentList(BaseMode, PopupsHandler):
return
elif chr(c) == 'q':
self.torrentview.update_marked(self.torrentview.cursel)
- self.set_minor_mode(QueueMode(self, self.torrentview._selected_torrent_ids()))
+ self.set_minor_mode(
+ QueueMode(self, self.torrentview._selected_torrent_ids())
+ )
return
elif chr(c) == '/':
self.set_minor_mode(SearchMode(self))
@@ -322,7 +336,9 @@ class TorrentList(BaseMode, PopupsHandler):
self.consoleui.set_mode('EventView')
return
elif chr(c) == 'S':
- self.config['torrentview']['show_sidebar'] = self.config['torrentview']['show_sidebar'] is False
+ self.config['torrentview']['show_sidebar'] = (
+ self.config['torrentview']['show_sidebar'] is False
+ )
self.config.save()
self.toggle_sidebar()
elif chr(c) == 'l':
diff --git a/deluge/ui/console/modes/torrentlist/torrentview.py b/deluge/ui/console/modes/torrentlist/torrentview.py
index e81ba6c99..67de3e786 100644
--- a/deluge/ui/console/modes/torrentlist/torrentview.py
+++ b/deluge/ui/console/modes/torrentlist/torrentview.py
@@ -16,7 +16,11 @@ from deluge.ui.console.modes.torrentlist import torrentviewcolumns
from deluge.ui.console.modes.torrentlist.torrentactions import torrent_actions_popup
from deluge.ui.console.utils import curses_util as util
from deluge.ui.console.utils import format_utils
-from deluge.ui.console.utils.column import get_column_value, get_required_fields, torrent_data_fields
+from deluge.ui.console.utils.column import (
+ get_column_value,
+ get_required_fields,
+ torrent_data_fields,
+)
from . import ACTION
@@ -85,7 +89,6 @@ for col_i, col_name in enumerate(torrentviewcolumns.column_pref_names):
class TorrentView(InputKeyHandler):
-
def __init__(self, torrentlist, config):
super(TorrentView, self).__init__()
self.torrentlist = torrentlist
@@ -226,6 +229,7 @@ class TorrentView(InputKeyHandler):
# and if it's a string
first_element = state[list(state)[0]]
if field in first_element:
+
def sort_key(s):
try:
# Sort case-insensitively but preserve A>a order.
@@ -250,7 +254,9 @@ class TorrentView(InputKeyHandler):
result = sort_by_field(state, result, s_primary)
if self.config['torrentview']['separate_complete']:
- result = sorted(result, key=lambda s: state.get(s).get('progress', 0) == 100.0)
+ result = sorted(
+ result, key=lambda s: state.get(s).get('progress', 0) == 100.0
+ )
return result
@@ -278,7 +284,9 @@ class TorrentView(InputKeyHandler):
if self.numtorrents == 0:
cols = self.torrentlist.torrentview_columns()
msg = 'No torrents match filter'.center(cols)
- self.torrentlist.add_string(3, '{!info!}%s' % msg, scr=self.torrentlist.torrentview_panel)
+ self.torrentlist.add_string(
+ 3, '{!info!}%s' % msg, scr=self.torrentlist.torrentview_panel
+ )
elif self.numtorrents == 0:
self.torrentlist.add_string(1, 'Waiting for torrents from core...')
return
@@ -290,7 +298,8 @@ class TorrentView(InputKeyHandler):
format_utils.format_row(
[get_column_value(name, ts) for name in self.cols_to_show],
self.column_widths,
- ), ts['state'],
+ ),
+ ts['state'],
)
return self.cached_rows[index]
@@ -321,14 +330,15 @@ class TorrentView(InputKeyHandler):
colorstr = '{!%(fg)s,%(bg)s!}' % colors
self.torrentlist.add_string(
- currow + self.torrentlist_offset, '%s%s' % (colorstr, row[0]),
- trim=False, scr=self.torrentlist.torrentview_panel,
+ currow + self.torrentlist_offset,
+ '%s%s' % (colorstr, row[0]),
+ trim=False,
+ scr=self.torrentlist.torrentview_panel,
)
def update(self, refresh=False):
d = component.get('SessionProxy').get_torrents_status(
- self.filter_dict,
- self.status_fields,
+ self.filter_dict, self.status_fields
)
d.addCallback(self.update_state, refresh=refresh)
@@ -338,15 +348,19 @@ class TorrentView(InputKeyHandler):
changed = None
for col in default_columns:
if col not in self.config['torrentview']['columns']:
- changed = self.config['torrentview']['columns'][col] = default_columns[col]
+ changed = self.config['torrentview']['columns'][col] = default_columns[
+ col
+ ]
if changed:
self.config.save()
self.cols_to_show = [
- col for col in sorted(
+ col
+ for col in sorted(
self.config['torrentview']['columns'],
key=lambda k: self.config['torrentview']['columns'][k]['order'],
- ) if self.config['torrentview']['columns'][col]['visible']
+ )
+ if self.config['torrentview']['columns'][col]['visible']
]
self.status_fields = get_required_fields(self.cols_to_show)
@@ -364,7 +378,10 @@ class TorrentView(InputKeyHandler):
self.update_columns()
def update_columns(self):
- self.column_widths = [self.config['torrentview']['columns'][col]['width'] for col in self.cols_to_show]
+ self.column_widths = [
+ self.config['torrentview']['columns'][col]['width']
+ for col in self.cols_to_show
+ ]
requested_width = sum(width for width in self.column_widths if width >= 0)
cols = self.torrentlist.torrentview_columns()
@@ -391,7 +408,7 @@ class TorrentView(InputKeyHandler):
# Trim the column if it's too long to fit
if len(ccol) > width:
- ccol = ccol[:width - 1]
+ ccol = ccol[: width - 1]
# Padding
ccol += ' ' * (width - len(ccol))
@@ -428,9 +445,12 @@ class TorrentView(InputKeyHandler):
def on_close(**kwargs):
if added:
self.marked.pop()
+
torrent_actions_popup(
- self.torrentlist, self._selected_torrent_ids(),
- action=ACTION.REMOVE, close_cb=on_close,
+ self.torrentlist,
+ self._selected_torrent_ids(),
+ action=ACTION.REMOVE,
+ close_cb=on_close,
)
elif c in [curses.KEY_ENTER, util.KEY_ENTER2] and self.numtorrents:
added = self.update_marked(self.cursel)
@@ -439,7 +459,12 @@ class TorrentView(InputKeyHandler):
if added:
self.marked.remove(self.cursel)
- torrent_actions_popup(self.torrentlist, self._selected_torrent_ids(), details=True, close_cb=on_close)
+ torrent_actions_popup(
+ self.torrentlist,
+ self._selected_torrent_ids(),
+ details=True,
+ close_cb=on_close,
+ )
self.torrentlist.refresh()
elif c == ord('j'):
affected_lines = self._scroll_up(1)
@@ -466,7 +491,11 @@ class TorrentView(InputKeyHandler):
added = self.update_marked(self.cursel, clear=True)
else:
self.last_mark = -1
- torrent_actions_popup(self.torrentlist, self._selected_torrent_ids(), action=ACTION.TORRENT_OPTIONS)
+ torrent_actions_popup(
+ self.torrentlist,
+ self._selected_torrent_ids(),
+ action=ACTION.TORRENT_OPTIONS,
+ )
elif c in [ord('>'), ord('<')]:
try:
i = self.cols_to_show.index(self.config['torrentview']['sort_primary'])
diff --git a/deluge/ui/console/modes/torrentlist/torrentviewcolumns.py b/deluge/ui/console/modes/torrentlist/torrentviewcolumns.py
index 96da7ffad..9dff84306 100644
--- a/deluge/ui/console/modes/torrentlist/torrentviewcolumns.py
+++ b/deluge/ui/console/modes/torrentlist/torrentviewcolumns.py
@@ -26,17 +26,39 @@ Control column visibilty with the following actions:
"""
column_pref_names = [
- 'queue', 'name', 'size', 'downloaded', 'uploaded', 'remaining', 'state',
- 'progress', 'seeds', 'peers', 'seeds_peers_ratio',
- 'download_speed', 'upload_speed', 'max_download_speed', 'max_upload_speed',
- 'eta', 'ratio', 'avail', 'time_added', 'completed_time', 'last_seen_complete',
- 'tracker', 'download_location', 'active_time', 'seeding_time', 'finished_time',
- 'time_since_transfer', 'shared', 'owner',
+ 'queue',
+ 'name',
+ 'size',
+ 'downloaded',
+ 'uploaded',
+ 'remaining',
+ 'state',
+ 'progress',
+ 'seeds',
+ 'peers',
+ 'seeds_peers_ratio',
+ 'download_speed',
+ 'upload_speed',
+ 'max_download_speed',
+ 'max_upload_speed',
+ 'eta',
+ 'ratio',
+ 'avail',
+ 'time_added',
+ 'completed_time',
+ 'last_seen_complete',
+ 'tracker',
+ 'download_location',
+ 'active_time',
+ 'seeding_time',
+ 'finished_time',
+ 'time_since_transfer',
+ 'shared',
+ 'owner',
]
class ColumnAndWidth(CheckedPlusInput):
-
def __init__(self, parent, name, message, child, on_width_func, **kwargs):
CheckedPlusInput.__init__(self, parent, name, message, child, **kwargs)
self.on_width_func = on_width_func
@@ -53,19 +75,19 @@ class ColumnAndWidth(CheckedPlusInput):
class TorrentViewColumns(InputPopup):
-
def __init__(self, torrentlist):
self.torrentlist = torrentlist
self.torrentview = torrentlist.torrentview
title = 'Visible columns (Esc to exit)'
InputPopup.__init__(
- self, torrentlist, title, close_cb=self._do_set_column_visibility,
+ self,
+ torrentlist,
+ title,
+ close_cb=self._do_set_column_visibility,
immediate_action=True,
height_req=len(column_pref_names) - 5,
- width_req=max(
- len(col) for col in column_pref_names + [title]
- ) + 14,
+ width_req=max(len(col) for col in column_pref_names + [title]) + 14,
border_off_west=1,
allow_rearrange=True,
)
@@ -76,21 +98,37 @@ class TorrentViewColumns(InputPopup):
for colpref_name in column_pref_names:
col = self.torrentview.config['torrentview']['columns'][colpref_name]
width_spin = IntSpinInput(
- self, colpref_name + '_ width', '', self.move, col['width'],
- min_val=-1, max_val=99, fmt='%2d',
+ self,
+ colpref_name + '_ width',
+ '',
+ self.move,
+ col['width'],
+ min_val=-1,
+ max_val=99,
+ fmt='%2d',
)
def on_width_func(name, width):
self.torrentview.config['torrentview']['columns'][name]['width'] = width
- self._add_input(ColumnAndWidth(
- self, colpref_name, torrent_data_fields[colpref_name]['name'], width_spin,
- on_width_func,
- checked=col['visible'], checked_char='*', msg_fmt=msg_fmt,
- show_usage_hints=False, child_always_visible=True,
- ))
+ self._add_input(
+ ColumnAndWidth(
+ self,
+ colpref_name,
+ torrent_data_fields[colpref_name]['name'],
+ width_spin,
+ on_width_func,
+ checked=col['visible'],
+ checked_char='*',
+ msg_fmt=msg_fmt,
+ show_usage_hints=False,
+ child_always_visible=True,
+ )
+ )
- def _do_set_column_visibility(self, data=None, state_changed=True, close=True, **kwargs):
+ def _do_set_column_visibility(
+ self, data=None, state_changed=True, close=True, **kwargs
+ ):
if close:
self.torrentlist.pop_popup()
return
@@ -98,8 +136,12 @@ class TorrentViewColumns(InputPopup):
return
for key, value in data.items():
- self.torrentview.config['torrentview']['columns'][key]['visible'] = value['value']
- self.torrentview.config['torrentview']['columns'][key]['order'] = value['order']
+ self.torrentview.config['torrentview']['columns'][key]['visible'] = value[
+ 'value'
+ ]
+ self.torrentview.config['torrentview']['columns'][key]['order'] = value[
+ 'order'
+ ]
self.torrentview.config.save()
self.torrentview.on_config_changed()
@@ -108,7 +150,13 @@ class TorrentViewColumns(InputPopup):
@overrides(InputPopup)
def handle_read(self, c):
if c == ord('h'):
- popup = MessagePopup(self.torrentlist, 'Help', COLUMN_VIEW_HELP_STR, width_req=70, border_off_west=1)
+ popup = MessagePopup(
+ self.torrentlist,
+ 'Help',
+ COLUMN_VIEW_HELP_STR,
+ width_req=70,
+ border_off_west=1,
+ )
self.torrentlist.push_popup(popup)
return util.ReadState.READ
return InputPopup.handle_read(self, c)
diff --git a/deluge/ui/console/parser.py b/deluge/ui/console/parser.py
index 35477c5bc..27f248564 100644
--- a/deluge/ui/console/parser.py
+++ b/deluge/ui/console/parser.py
@@ -21,7 +21,6 @@ class OptionParserError(Exception):
class ConsoleBaseParser(argparse.ArgumentParser):
-
def format_help(self):
"""Differs from ArgumentParser.format_help by adding the raw epilog
as formatted in the string. Default bahavior mangles the formatting.
@@ -38,7 +37,6 @@ class ConsoleBaseParser(argparse.ArgumentParser):
class ConsoleCommandParser(ConsoleBaseParser):
-
def _split_args(self, args):
command_options = []
for a in args:
@@ -72,6 +70,7 @@ class ConsoleCommandParser(ConsoleBaseParser):
argparse.Namespace: The parsed arguments.
"""
from deluge.ui.ui_entry import AMBIGUOUS_CMD_ARGS
+
self.base_parser.parse_known_ui_args(args, withhold=AMBIGUOUS_CMD_ARGS)
multi_command = self._split_args(args)
@@ -107,7 +106,6 @@ class ConsoleCommandParser(ConsoleBaseParser):
class OptionParser(ConsoleBaseParser):
-
def __init__(self, **kwargs):
super(OptionParser, self).__init__(**kwargs)
self.formatter = ConsoleColorFormatter()
diff --git a/deluge/ui/console/utils/colors.py b/deluge/ui/console/utils/colors.py
index a6523fd06..c07f3e4d4 100644
--- a/deluge/ui/console/utils/colors.py
+++ b/deluge/ui/console/utils/colors.py
@@ -33,9 +33,7 @@ colors = [
]
# {(fg, bg): pair_number, ...}
-color_pairs = {
- ('white', 'black'): 0, # Special case, can't be changed
-}
+color_pairs = {('white', 'black'): 0} # Special case, can't be changed
# Some default color schemes
schemes = {
@@ -101,7 +99,13 @@ def init_colors():
counter = 1
for fg in colors:
for bg in colors:
- counter = define_pair(counter, fg[6:].lower(), bg[6:].lower(), getattr(curses, fg), getattr(curses, bg))
+ counter = define_pair(
+ counter,
+ fg[6:].lower(),
+ bg[6:].lower(),
+ getattr(curses, fg),
+ getattr(curses, bg),
+ )
counter = define_pair(counter, 'white', 'grey', curses.COLOR_WHITE, 241)
counter = define_pair(counter, 'black', 'whitegrey', curses.COLOR_BLACK, 249)
@@ -124,7 +128,7 @@ def replace_tabs(line):
"""
for i in range(line.count(tab_char)):
- tab_length = 8 - (len(line[:line.find(tab_char)]) % 8)
+ tab_length = 8 - (len(line[: line.find(tab_char)]) % 8)
line = line.replace(tab_char, b' ' * tab_length, 1)
return line
@@ -187,14 +191,21 @@ def parse_color_string(s, encoding='UTF-8'):
while s.find(color_tag_start) != -1:
begin = s.find(color_tag_start)
if begin > 0:
- ret.append((curses.color_pair(color_pairs[(schemes['input'][0], schemes['input'][1])]), s[:begin]))
+ ret.append(
+ (
+ curses.color_pair(
+ color_pairs[(schemes['input'][0], schemes['input'][1])]
+ ),
+ s[:begin],
+ )
+ )
end = s.find(color_tag_end)
if end == -1:
raise BadColorString('Missing closing "!}"')
# Get a list of attributes in the bracketed section
- attrs = s[begin + 2:end].split(',')
+ attrs = s[begin + 2 : end].split(',')
if len(attrs) == 1 and not attrs[0].strip(' '):
raise BadColorString('No description in {! !}')
@@ -230,7 +241,10 @@ def parse_color_string(s, encoding='UTF-8'):
if attrs[0][0] in ['+', '-']:
# Color is not given, so use last color
if last_color_attr is None:
- raise BadColorString('No color value given when no previous color was used!: %s' % (attrs[0]))
+ raise BadColorString(
+ 'No color value given when no previous color was used!: %s'
+ % (attrs[0])
+ )
color_pair = last_color_attr
for i, attr in enumerate(attrs):
if attr[1:] not in attrlist:
@@ -268,10 +282,10 @@ def parse_color_string(s, encoding='UTF-8'):
next_begin = s.find(color_tag_start, end)
if next_begin == -1:
- ret.append((color_pair, replace_tabs(s[end + 2:])))
+ ret.append((color_pair, replace_tabs(s[end + 2 :])))
break
else:
- ret.append((color_pair, replace_tabs(s[end + 2:next_begin])))
+ ret.append((color_pair, replace_tabs(s[end + 2 : next_begin])))
s = s[next_begin:]
if not ret:
@@ -289,7 +303,6 @@ class ConsoleColorFormatter(object):
'<torrent-id>': '{!green!}%s{!input!}',
'<torrent>': '{!green!}%s{!input!}',
'<command>': '{!green!}%s{!input!}',
-
'<state>': '{!yellow!}%s{!input!}',
'\\.\\.\\.': '{!yellow!}%s{!input!}',
'\\s\\*\\s': '{!blue!}%s{!input!}',
@@ -297,7 +310,6 @@ class ConsoleColorFormatter(object):
# "(\-[a-zA-Z0-9])": "{!red!}%s{!input!}",
'--[_\\-a-zA-Z0-9]+': '{!green!}%s{!input!}',
'(\\[|\\])': '{!info!}%s{!input!}',
-
'<tab>': '{!white!}%s{!input!}',
'[_A-Z]{3,}': '{!cyan!}%s{!input!}',
'<key>': '{!cyan!}%s{!input!}',
@@ -305,12 +317,12 @@ class ConsoleColorFormatter(object):
'usage:': '{!info!}%s{!input!}',
'<download-folder>': '{!yellow!}%s{!input!}',
'<torrent-file>': '{!green!}%s{!input!}',
-
}
def format_colors(self, string):
def r(repl):
return lambda s: repl % s.group()
+
for key, replacement in self.replace_dict.items():
string = re.sub(key, r(replacement), string)
return string
diff --git a/deluge/ui/console/utils/column.py b/deluge/ui/console/utils/column.py
index cf3d64be9..47b0b2433 100644
--- a/deluge/ui/console/utils/column.py
+++ b/deluge/ui/console/utils/column.py
@@ -30,33 +30,26 @@ formatters = {
'tracker': None,
'download_location': None,
'owner': None,
-
'progress_state': format_utils.format_progress,
'progress': format_utils.format_progress,
-
'size': format_utils.format_size,
'downloaded': format_utils.format_size,
'uploaded': format_utils.format_size,
'remaining': format_utils.format_size,
-
'ratio': format_utils.format_float,
'avail': format_utils.format_float,
'seeds_peers_ratio': format_utils.format_float,
-
'download_speed': format_utils.format_speed,
'upload_speed': format_utils.format_speed,
'max_download_speed': format_utils.format_speed,
'max_upload_speed': format_utils.format_speed,
-
'peers': format_utils.format_seeds_peers,
'seeds': format_utils.format_seeds_peers,
-
'time_added': deluge.common.fdate,
'seeding_time': format_utils.format_time,
'active_time': format_utils.format_time,
'time_since_transfer': format_utils.format_date_dash,
'finished_time': deluge.common.ftime,
-
'last_seen_complete': format_utils.format_date_never,
'completed_time': format_utils.format_date_dash,
'eta': format_utils.format_time,
diff --git a/deluge/ui/console/utils/format_utils.py b/deluge/ui/console/utils/format_utils.py
index 9d609c4fb..6b6d8d483 100644
--- a/deluge/ui/console/utils/format_utils.py
+++ b/deluge/ui/console/utils/format_utils.py
@@ -142,7 +142,7 @@ def trim_string(string, w, have_dbls):
chrs.append('.')
return '%s ' % (''.join(chrs))
else:
- return '%s ' % (string[0:w - 1])
+ return '%s ' % (string[0 : w - 1])
def format_column(col, lim):
@@ -161,7 +161,9 @@ def format_column(col, lim):
def format_row(row, column_widths):
- return ''.join([format_column(row[i], column_widths[i]) for i in range(0, len(row))])
+ return ''.join(
+ [format_column(row[i], column_widths[i]) for i in range(0, len(row))]
+ )
_strip_re = re.compile(r'\{!.*?!\}')
@@ -183,7 +185,7 @@ def shorten_hash(tid, space_left, min_width=13, placeholder='...'):
if space_left >= min_width:
mid = len(tid) // 2
trim, remain = divmod(len(tid) + len(placeholder) - space_left, 2)
- return tid[0: mid - trim] + placeholder + tid[mid + trim + remain:]
+ return tid[0 : mid - trim] + placeholder + tid[mid + trim + remain :]
else:
# Justity the tid so it is completely on the next line.
return tid.rjust(len(tid) + space_left)
@@ -218,7 +220,7 @@ def wrap_string(string, width, min_lines=0, strip_colors=True):
m = _format_code.search(remove_formatting(s))
if m:
if m.group(1).startswith('indent:'):
- indent = m.group(1)[len('indent:'):]
+ indent = m.group(1)[len('indent:') :]
elif m.group(1).startswith('indent_pos:'):
begin = m.start(0)
indent = ' ' * begin
diff --git a/deluge/ui/console/widgets/fields.py b/deluge/ui/console/widgets/fields.py
index e5b9ece76..ae6da34e9 100644
--- a/deluge/ui/console/widgets/fields.py
+++ b/deluge/ui/console/widgets/fields.py
@@ -18,7 +18,11 @@ from deluge.decorators import overrides
from deluge.ui.console.modes.basemode import InputKeyHandler
from deluge.ui.console.utils import colors
from deluge.ui.console.utils import curses_util as util
-from deluge.ui.console.utils.format_utils import delete_alt_backspace, remove_formatting, wrap_string
+from deluge.ui.console.utils.format_utils import (
+ delete_alt_backspace,
+ remove_formatting,
+ wrap_string,
+)
try:
import curses
@@ -29,7 +33,6 @@ log = logging.getLogger(__name__)
class BaseField(InputKeyHandler):
-
def __init__(self, parent=None, name=None, selectable=True, **kwargs):
super(BaseField, self).__init__()
self.name = name
@@ -70,7 +73,12 @@ class BaseField(InputKeyHandler):
def build_fmt_string(self, focused, active, value_key='msg', **kwargs):
color_key, font_key = self.get_fmt_keys(focused, active, **kwargs)
- return '{!%%(%s)s,%%(%s)s!}%%(%s)s{!%%(%s)s!}' % (color_key, font_key, value_key, 'color_end')
+ return '{!%%(%s)s,%%(%s)s!}%%(%s)s{!%%(%s)s!}' % (
+ color_key,
+ font_key,
+ value_key,
+ 'color_end',
+ )
def depend_skip(self):
return False
@@ -97,14 +105,12 @@ class BaseField(InputKeyHandler):
class NoInputField(BaseField):
-
@overrides(BaseField)
def has_input(self):
return False
class InputField(BaseField):
-
def __init__(self, parent, name, message, format_default=None, **kwargs):
BaseField.__init__(self, parent=parent, name=name, **kwargs)
self.format_default = format_default
@@ -140,7 +146,6 @@ class InputField(BaseField):
class Header(NoInputField):
-
def __init__(self, parent, header, space_above, space_below, **kwargs):
if 'name' not in kwargs:
kwargs['name'] = header
@@ -166,7 +171,6 @@ class Header(NoInputField):
class InfoField(NoInputField):
-
def __init__(self, parent, name, label, value, **kwargs):
NoInputField.__init__(self, parent=parent, name=name, **kwargs)
self.label = label
@@ -188,17 +192,27 @@ class InfoField(NoInputField):
class CheckedInput(InputField):
-
def __init__(
- self, parent, name, message, checked=False, checked_char='X', unchecked_char=' ',
- checkbox_format='[%s] ', **kwargs
+ self,
+ parent,
+ name,
+ message,
+ checked=False,
+ checked_char='X',
+ unchecked_char=' ',
+ checkbox_format='[%s] ',
+ **kwargs
):
InputField.__init__(self, parent, name, message, **kwargs)
self.set_value(checked)
- self.fmt_keys.update({
- 'msg': message, 'checkbox_format': checkbox_format,
- 'unchecked_char': unchecked_char, 'checked_char': checked_char,
- })
+ self.fmt_keys.update(
+ {
+ 'msg': message,
+ 'checkbox_format': checkbox_format,
+ 'unchecked_char': unchecked_char,
+ 'checked_char': checked_char,
+ }
+ )
self.set_fmt_key('font_checked', 'font', kwargs)
self.set_fmt_key('font_unfocused_checked', 'font_checked', kwargs)
self.set_fmt_key('font_active_checked', 'font_active', kwargs)
@@ -206,7 +220,9 @@ class CheckedInput(InputField):
self.set_fmt_key('color_checked', 'color', kwargs)
self.set_fmt_key('color_active_checked', 'color_active', kwargs)
self.set_fmt_key('color_unfocused_checked', 'color_checked', kwargs)
- self.set_fmt_key('color_unfocused_active_checked', 'color_unfocused_active', kwargs)
+ self.set_fmt_key(
+ 'color_unfocused_active_checked', 'color_unfocused_active', kwargs
+ )
@property
def checked(self):
@@ -214,7 +230,9 @@ class CheckedInput(InputField):
@overrides(BaseField)
def get_fmt_keys(self, focused, active, **kwargs):
- color_key, font_key = super(CheckedInput, self).get_fmt_keys(focused, active, **kwargs)
+ color_key, font_key = super(CheckedInput, self).get_fmt_keys(
+ focused, active, **kwargs
+ )
if self.checked:
color_key += '_checked'
font_key += '_checked'
@@ -256,10 +274,16 @@ class CheckedInput(InputField):
class CheckedPlusInput(CheckedInput):
-
def __init__(
- self, parent, name, message, child, child_always_visible=False,
- show_usage_hints=True, msg_fmt='%s ', **kwargs
+ self,
+ parent,
+ name,
+ message,
+ child,
+ child_always_visible=False,
+ show_usage_hints=True,
+ msg_fmt='%s ',
+ **kwargs
):
CheckedInput.__init__(self, parent, name, message, **kwargs)
self.child = child
@@ -273,28 +297,42 @@ class CheckedPlusInput(CheckedInput):
return max(2 if self.show_usage_hints else 1, self.child.height)
@overrides(CheckedInput)
- def render(self, screen, row, width=None, active=False, focused=False, col=0, **kwargs):
+ def render(
+ self, screen, row, width=None, active=False, focused=False, col=0, **kwargs
+ ):
isact = active and not self.child_active
- CheckedInput.render(self, screen, row, width=width, active=isact, focused=focused, col=col)
+ CheckedInput.render(
+ self, screen, row, width=width, active=isact, focused=focused, col=col
+ )
rows = 1
- if self.show_usage_hints and (self.child_always_visible or (active and self.checked)):
+ if self.show_usage_hints and (
+ self.child_always_visible or (active and self.checked)
+ ):
msg = '(esc to leave)' if self.child_active else '(right arrow to edit)'
self.parent.add_string(row + 1, msg, scr=screen, col=col, pad=False)
rows += 1
- msglen = len(self.msg_fmt % colors.strip_colors(self.build_msg_string(focused, active)))
+ msglen = len(
+ self.msg_fmt % colors.strip_colors(self.build_msg_string(focused, active))
+ )
# show child
if self.checked or self.child_always_visible:
crows = self.child.render(
- screen, row, width=width - msglen,
+ screen,
+ row,
+ width=width - msglen,
active=self.child_active and active,
- col=col + msglen, cursor_offset=msglen,
+ col=col + msglen,
+ cursor_offset=msglen,
)
rows = max(rows, crows)
else:
self.parent.add_string(
- row, '(enable to view/edit value)', scr=screen,
- col=col + msglen, pad=False,
+ row,
+ '(enable to view/edit value)',
+ scr=screen,
+ col=col + msglen,
+ pad=False,
)
return rows
@@ -320,10 +358,20 @@ class CheckedPlusInput(CheckedInput):
class IntSpinInput(InputField):
-
def __init__(
- self, parent, name, message, move_func, value, min_val=None, max_val=None,
- inc_amt=1, incr_large=10, strict_validation=False, fmt='%d', **kwargs
+ self,
+ parent,
+ name,
+ message,
+ move_func,
+ value,
+ min_val=None,
+ max_val=None,
+ inc_amt=1,
+ incr_large=10,
+ strict_validation=False,
+ fmt='%d',
+ **kwargs
):
InputField.__init__(self, parent, name, message, **kwargs)
self.convert_func = int
@@ -335,7 +383,9 @@ class IntSpinInput(InputField):
self.last_valid_value = self.value
self.last_active = False
self.cursor = len(self.valstr)
- self.cursoff = colors.get_line_width(self.message) + 3 # + 4 for the " [ " in the rendered string
+ self.cursoff = (
+ colors.get_line_width(self.message) + 3
+ ) # + 4 for the " [ " in the rendered string
self.move_func = move_func
self.strict_validation = strict_validation
self.min_val = min_val
@@ -351,11 +401,15 @@ class IntSpinInput(InputField):
return value
@overrides(InputField)
- def render(self, screen, row, active=False, focused=True, col=0, cursor_offset=0, **kwargs):
+ def render(
+ self, screen, row, active=False, focused=True, col=0, cursor_offset=0, **kwargs
+ ):
if active:
self.last_active = True
elif self.last_active:
- self.set_value(self.valstr, validate=True, value_on_fail=self.last_valid_value)
+ self.set_value(
+ self.valstr, validate=True, value_on_fail=self.last_valid_value
+ )
self.last_active = False
fmt_str = self.build_fmt_string(focused, active, value_key='value')
@@ -368,11 +422,12 @@ class IntSpinInput(InputField):
value_format += '[ ' + fmt_str + ' ]'
self.parent.add_string(
- row, value_format % dict(
- {'msg': self.message, 'value': '%s' % self.valstr},
- **self.fmt_keys
- ),
- scr=screen, col=col, pad=False,
+ row,
+ value_format
+ % dict({'msg': self.message, 'value': '%s' % self.valstr}, **self.fmt_keys),
+ scr=screen,
+ col=col,
+ pad=False,
)
if active:
if focused:
@@ -404,9 +459,12 @@ class IntSpinInput(InputField):
self.cursor = len(self.valstr)
elif c == curses.KEY_BACKSPACE or c == util.KEY_BACKSPACE2:
if self.valstr and self.cursor > 0:
- new_val = self.valstr[:self.cursor - 1] + self.valstr[self.cursor:]
+ new_val = self.valstr[: self.cursor - 1] + self.valstr[self.cursor :]
self.set_value(
- new_val, validate=False, cursor=self.cursor - 1, cursor_on_fail=True,
+ new_val,
+ validate=False,
+ cursor=self.cursor - 1,
+ cursor_on_fail=True,
value_on_fail=self.valstr if self.strict_validation else None,
)
elif c == curses.KEY_DC: # Del
@@ -414,39 +472,74 @@ class IntSpinInput(InputField):
if self.cursor == 0:
new_val = self.valstr[1:]
else:
- new_val = self.valstr[:self.cursor] + self.valstr[self.cursor + 1:]
+ new_val = (
+ self.valstr[: self.cursor] + self.valstr[self.cursor + 1 :]
+ )
self.set_value(
- new_val, validate=False, cursor=False,
- value_on_fail=self.valstr if self.strict_validation else None, cursor_on_fail=True,
+ new_val,
+ validate=False,
+ cursor=False,
+ value_on_fail=self.valstr if self.strict_validation else None,
+ cursor_on_fail=True,
)
elif c == ord('-'): # minus
self.set_value(
- self.value - 1, validate=True, cursor=True, cursor_on_fail=True,
- value_on_fail=self.value, on_invalid=self.value,
+ self.value - 1,
+ validate=True,
+ cursor=True,
+ cursor_on_fail=True,
+ value_on_fail=self.value,
+ on_invalid=self.value,
)
elif c == ord('+'): # plus
self.set_value(
- self.value + 1, validate=True, cursor=True, cursor_on_fail=True,
- value_on_fail=self.value, on_invalid=self.value,
+ self.value + 1,
+ validate=True,
+ cursor=True,
+ cursor_on_fail=True,
+ value_on_fail=self.value,
+ on_invalid=self.value,
)
elif util.is_int_chr(c):
if self.strict_validation:
- new_val = self.valstr[:self.cursor - 1] + chr(c) + self.valstr[self.cursor - 1:]
+ new_val = (
+ self.valstr[: self.cursor - 1]
+ + chr(c)
+ + self.valstr[self.cursor - 1 :]
+ )
self.set_value(
- new_val, validate=True, cursor=self.cursor + 1,
- value_on_fail=self.valstr, on_invalid=self.value,
+ new_val,
+ validate=True,
+ cursor=self.cursor + 1,
+ value_on_fail=self.valstr,
+ on_invalid=self.value,
)
else:
minus_place = self.valstr.find('-')
if self.cursor > minus_place:
- new_val = self.valstr[:self.cursor] + chr(c) + self.valstr[self.cursor:]
- self.set_value(new_val, validate=True, cursor=self.cursor + 1, on_invalid=self.value)
+ new_val = (
+ self.valstr[: self.cursor] + chr(c) + self.valstr[self.cursor :]
+ )
+ self.set_value(
+ new_val,
+ validate=True,
+ cursor=self.cursor + 1,
+ on_invalid=self.value,
+ )
else:
return util.ReadState.IGNORED
return util.ReadState.READ
@overrides(BaseField)
- def set_value(self, val, cursor=True, validate=False, cursor_on_fail=False, value_on_fail=None, on_invalid=None):
+ def set_value(
+ self,
+ val,
+ cursor=True,
+ validate=False,
+ cursor_on_fail=False,
+ value_on_fail=None,
+ on_invalid=None,
+ ):
value = None
try:
value = self.convert_func(val)
@@ -467,8 +560,11 @@ class IntSpinInput(InputField):
except ValueError:
if value_on_fail is not None:
self.set_value(
- value_on_fail, cursor=cursor, cursor_on_fail=cursor_on_fail,
- validate=validate, on_invalid=on_invalid,
+ value_on_fail,
+ cursor=cursor,
+ cursor_on_fail=cursor_on_fail,
+ validate=validate,
+ on_invalid=on_invalid,
)
return
self.value = None
@@ -477,6 +573,7 @@ class IntSpinInput(InputField):
self.cursor = cursor
except TypeError:
import traceback
+
log.warning('TypeError: %s', ''.join(traceback.format_exc()))
else:
if cursor is True:
@@ -486,7 +583,6 @@ class IntSpinInput(InputField):
class FloatSpinInput(IntSpinInput):
-
def __init__(self, parent, message, name, move_func, value, precision=1, **kwargs):
self.precision = precision
IntSpinInput.__init__(self, parent, message, name, move_func, value, **kwargs)
@@ -504,17 +600,24 @@ class FloatSpinInput(IntSpinInput):
point_place = self.valstr.find('.')
if point_place >= 0:
return util.ReadState.READ
- new_val = self.valstr[:self.cursor] + chr(c) + self.valstr[self.cursor:]
+ new_val = self.valstr[: self.cursor] + chr(c) + self.valstr[self.cursor :]
self.set_value(new_val, validate=True, cursor=self.cursor + 1)
else:
return IntSpinInput.handle_read(self, c)
class SelectInput(InputField):
-
def __init__(
- self, parent, name, message, opts, vals, active_index, active_default=False,
- require_select_action=True, **kwargs
+ self,
+ parent,
+ name,
+ message,
+ opts,
+ vals,
+ active_index,
+ active_default=False,
+ require_select_action=True,
+ **kwargs
):
InputField.__init__(self, parent, name, message, **kwargs)
self.opts = opts
@@ -529,21 +632,33 @@ class SelectInput(InputField):
self.set_fmt_key('font_selected', font_selected, kwargs)
self.set_fmt_key('font_active_selected', 'font_selected', kwargs)
self.set_fmt_key('font_unfocused_selected', 'font_selected', kwargs)
- self.set_fmt_key('font_unfocused_active_selected', 'font_active_selected', kwargs)
+ self.set_fmt_key(
+ 'font_unfocused_active_selected', 'font_active_selected', kwargs
+ )
self.set_fmt_key('color_selected', 'color', kwargs)
self.set_fmt_key('color_active_selected', 'color_active', kwargs)
self.set_fmt_key('color_unfocused_selected', 'color_selected', kwargs)
- self.set_fmt_key('color_unfocused_active_selected', 'color_unfocused_active', kwargs)
+ self.set_fmt_key(
+ 'color_unfocused_active_selected', 'color_unfocused_active', kwargs
+ )
self.set_fmt_key('color_default_value', 'magenta,black', kwargs)
self.set_fmt_key('color_default_value', 'magenta,black')
self.set_fmt_key('color_default_value_active', 'magentadark,white')
self.set_fmt_key('color_default_value_selected', 'color_default_value', kwargs)
self.set_fmt_key('color_default_value_unfocused', 'color_default_value', kwargs)
- self.set_fmt_key('color_default_value_unfocused_selected', 'color_default_value_selected', kwargs)
+ self.set_fmt_key(
+ 'color_default_value_unfocused_selected',
+ 'color_default_value_selected',
+ kwargs,
+ )
self.set_fmt_key('color_default_value_active_selected', 'magentadark,white')
- self.set_fmt_key('color_default_value_unfocused_active_selected', 'color_unfocused_active', kwargs)
+ self.set_fmt_key(
+ 'color_default_value_unfocused_active_selected',
+ 'color_unfocused_active',
+ kwargs,
+ )
@property
def height(self):
@@ -551,7 +666,9 @@ class SelectInput(InputField):
@overrides(BaseField)
def get_fmt_keys(self, focused, active, selected=False, **kwargs):
- color_key, font_key = super(SelectInput, self).get_fmt_keys(focused, active, **kwargs)
+ color_key, font_key = super(SelectInput, self).get_fmt_keys(
+ focused, active, **kwargs
+ )
if selected:
color_key += '_selected'
font_key += '_selected'
@@ -569,7 +686,9 @@ class SelectInput(InputField):
fmt_args = {'selected': i == self.selected_index}
if i == self.default_option:
fmt_args['color_key'] = 'color_default_value'
- fmt = self.build_fmt_string(focused, (i == self.active_index) and active, **fmt_args)
+ fmt = self.build_fmt_string(
+ focused, (i == self.active_index) and active, **fmt_args
+ )
string = '[%s]' % (fmt % self.fmt_keys)
self.parent.add_string(row, string, scr=screen, col=off, pad=False)
off += len(opt) + 3
@@ -609,10 +728,17 @@ class SelectInput(InputField):
class TextInput(InputField):
-
def __init__(
- self, parent, name, message, move_func, width, value, complete=False,
- activate_input=False, **kwargs
+ self,
+ parent,
+ name,
+ message,
+ move_func,
+ width,
+ value,
+ complete=False,
+ activate_input=False,
+ **kwargs
):
InputField.__init__(self, parent, name, message, **kwargs)
self.move_func = move_func
@@ -649,7 +775,7 @@ class TextInput(InputField):
c_pos_abs = len(self.value) - cursor_width
new_cur = c_pos_abs + 1
self.value_offset = new_cur
- vstr = self.value[self.value_offset:]
+ vstr = self.value[self.value_offset :]
if len(vstr) > cursor_width:
vstr = vstr[:cursor_width]
@@ -660,7 +786,7 @@ class TextInput(InputField):
vstr = self.value.ljust(cursor_width)
else:
self.value_offset = min(self.value_offset, self.cursor)
- vstr = self.value[self.value_offset:]
+ vstr = self.value[self.value_offset :]
if len(vstr) > cursor_width:
vstr = vstr[:cursor_width]
vstr = vstr.ljust(cursor_width)
@@ -679,7 +805,17 @@ class TextInput(InputField):
return min(width - 1 + col, x_pos)
@overrides(InputField)
- def render(self, screen, row, width=None, active=False, focused=True, col=0, cursor_offset=0, **kwargs):
+ def render(
+ self,
+ screen,
+ row,
+ width=None,
+ active=False,
+ focused=True,
+ col=0,
+ cursor_offset=0,
+ **kwargs
+ ):
if not self.value and not active and len(self.default_value) != 0:
self.value = self.default_value
self.cursor = len(self.value)
@@ -692,20 +828,30 @@ class TextInput(InputField):
if active:
if self.opts:
- self.parent.add_string(row + 1, self.opts[self.opt_off:], scr=screen, col=col, pad=False)
+ self.parent.add_string(
+ row + 1, self.opts[self.opt_off :], scr=screen, col=col, pad=False
+ )
if focused and self.input_active:
- util.safe_curs_set(util.Curser.NORMAL) # Make cursor visible when text field is focused
+ util.safe_curs_set(
+ util.Curser.NORMAL
+ ) # Make cursor visible when text field is focused
x_pos = self.calculate_cursor_pos(width, col)
self.move_func(row, x_pos)
fmt = '{!black,white,bold!}%s'
- if self.format_default and len(self.value) != 0 and self.value == self.default_value:
+ if (
+ self.format_default
+ and len(self.value) != 0
+ and self.value == self.default_value
+ ):
fmt = '{!magenta,white!}%s'
if not active or not focused or self.input_active:
fmt = '{!white,grey,bold!}%s'
- self.parent.add_string(row, fmt % vstr, scr=screen, col=col, pad=False, trim=False)
+ self.parent.add_string(
+ row, fmt % vstr, scr=screen, col=col, pad=False, trim=False
+ )
return self.height
@overrides(BaseField)
@@ -723,8 +869,12 @@ class TextInput(InputField):
if self.activate_input:
if not self.input_active:
if c in [
- curses.KEY_LEFT, curses.KEY_RIGHT, curses.KEY_HOME,
- curses.KEY_END, curses.KEY_ENTER, util.KEY_ENTER2,
+ curses.KEY_LEFT,
+ curses.KEY_RIGHT,
+ curses.KEY_HOME,
+ curses.KEY_END,
+ curses.KEY_ENTER,
+ util.KEY_ENTER2,
]:
self.input_active = True
return util.ReadState.READ
@@ -752,7 +902,9 @@ class TextInput(InputField):
# now find previous double space, best guess at a split point
# in future could keep opts unjoined to get this really right
self.opt_off = self.opts.rfind(' ', 0, self.opt_off) + 2
- if second_hit and self.opt_off == prev: # double tap and we're at the end
+ if (
+ second_hit and self.opt_off == prev
+ ): # double tap and we're at the end
self.opt_off = 0
else:
opts = self.do_complete(self.value)
@@ -766,7 +918,9 @@ class TextInput(InputField):
self.value = prefix
self.cursor = len(prefix)
- if len(opts) > 1 and second_hit: # display multiple options on second tab hit
+ if (
+ len(opts) > 1 and second_hit
+ ): # display multiple options on second tab hit
sp = self.value.rfind(os.sep) + 1
self.opts = ' '.join([o[sp:] for o in opts])
@@ -783,13 +937,16 @@ class TextInput(InputField):
# Delete a character in the input string based on cursor position
elif c == curses.KEY_BACKSPACE or c == util.KEY_BACKSPACE2:
if self.value and self.cursor > 0:
- self.value = self.value[:self.cursor - 1] + self.value[self.cursor:]
+ self.value = self.value[: self.cursor - 1] + self.value[self.cursor :]
self.cursor -= 1
- elif c == [util.KEY_ESC, util.KEY_BACKSPACE2] or c == [util.KEY_ESC, curses.KEY_BACKSPACE]:
+ elif c == [util.KEY_ESC, util.KEY_BACKSPACE2] or c == [
+ util.KEY_ESC,
+ curses.KEY_BACKSPACE,
+ ]:
self.value, self.cursor = delete_alt_backspace(self.value, self.cursor)
elif c == curses.KEY_DC:
if self.value and self.cursor < len(self.value):
- self.value = self.value[:self.cursor] + self.value[self.cursor + 1:]
+ self.value = self.value[: self.cursor] + self.value[self.cursor + 1 :]
elif c > 31 and c < 256:
# Emulate getwch
stroke = chr(c)
@@ -805,7 +962,9 @@ class TextInput(InputField):
self.value += uchar
else:
# Insert into string
- self.value = self.value[:self.cursor] + uchar + self.value[self.cursor:]
+ self.value = (
+ self.value[: self.cursor] + uchar + self.value[self.cursor :]
+ )
# Move the cursor forward
self.cursor += 1
@@ -853,8 +1012,9 @@ class TextInput(InputField):
class ComboInput(InputField):
-
- def __init__(self, parent, name, message, choices, default=None, searchable=True, **kwargs):
+ def __init__(
+ self, parent, name, message, choices, default=None, searchable=True, **kwargs
+ ):
InputField.__init__(self, parent, name, message, **kwargs)
self.choices = choices
self.default = default
@@ -900,17 +1060,27 @@ class ComboInput(InputField):
# No match, so start at beginning
select_in_range(0, selected)
- from deluge.ui.console.widgets.popup import SelectablePopup # Must import here
+ from deluge.ui.console.widgets.popup import (
+ SelectablePopup,
+ ) # Must import here
+
select_popup = SelectablePopup(
- self.parent, ' %s ' % _('Select Language'), self._lang_selected,
+ self.parent,
+ ' %s ' % _('Select Language'),
+ self._lang_selected,
input_cb=search_handler if self.searchable else None,
- border_off_west=1, active_wrap=False, width_req=self.choices_width + 12,
+ border_off_west=1,
+ active_wrap=False,
+ width_req=self.choices_width + 12,
)
for choice in self.choices:
args = {'data': choice[0]}
select_popup.add_line(
- choice[0], choice[1], selectable=True,
- selected=choice[0] == self.get_value(), **args
+ choice[0],
+ choice[1],
+ selectable=True,
+ selected=choice[0] == self.get_value(),
+ **args
)
self.parent.push_popup(select_popup)
return util.ReadState.CHANGED
@@ -925,14 +1095,17 @@ class ComboInput(InputField):
msg = c[1]
break
if msg is None:
- log.warning('Setting value "%s" found nothing in choices: %s', val, self.choices)
+ log.warning(
+ 'Setting value "%s" found nothing in choices: %s', val, self.choices
+ )
self.fmt_keys.update({'msg': msg})
class TextField(BaseField):
-
def __init__(self, parent, name, value, selectable=True, value_fmt='%s', **kwargs):
- BaseField.__init__(self, parent=parent, name=name, selectable=selectable, **kwargs)
+ BaseField.__init__(
+ self, parent=parent, name=name, selectable=selectable, **kwargs
+ )
self.value = value
self.value_fmt = value_fmt
self.set_value(value)
@@ -948,7 +1121,9 @@ class TextField(BaseField):
@overrides(BaseField)
def render(self, screen, row, active=False, focused=False, col=0, **kwargs):
- util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active
+ util.safe_curs_set(
+ util.Curser.INVISIBLE
+ ) # Make cursor invisible when text field is active
fmt = self.build_fmt_string(focused, active)
self.fmt_keys['msg'] = self.txt
string = fmt % self.fmt_keys
@@ -957,18 +1132,28 @@ class TextField(BaseField):
class TextArea(TextField):
-
def __init__(self, parent, name, value, value_fmt='%s', **kwargs):
- TextField.__init__(self, parent, name, value, selectable=False, value_fmt=value_fmt, **kwargs)
+ TextField.__init__(
+ self, parent, name, value, selectable=False, value_fmt=value_fmt, **kwargs
+ )
@overrides(TextField)
def render(self, screen, row, col=0, **kwargs):
- util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active
+ util.safe_curs_set(
+ util.Curser.INVISIBLE
+ ) # Make cursor invisible when text field is active
color = '{!white,black!}'
lines = wrap_string(self.txt, self.parent.width - 3, 3, True)
for i, line in enumerate(lines):
- self.parent.add_string(row + i, '%s%s' % (color, line), scr=screen, col=col, pad=False, trim=False)
+ self.parent.add_string(
+ row + i,
+ '%s%s' % (color, line),
+ scr=screen,
+ col=col,
+ pad=False,
+ trim=False,
+ )
return len(lines)
@property
@@ -982,9 +1167,19 @@ class TextArea(TextField):
class DividerField(NoInputField):
-
- def __init__(self, parent, name, value, selectable=False, fill_width=True, value_fmt='%s', **kwargs):
- NoInputField.__init__(self, parent=parent, name=name, selectable=selectable, **kwargs)
+ def __init__(
+ self,
+ parent,
+ name,
+ value,
+ selectable=False,
+ fill_width=True,
+ value_fmt='%s',
+ **kwargs
+ ):
+ NoInputField.__init__(
+ self, parent=parent, name=name, selectable=selectable, **kwargs
+ )
self.value = value
self.value_fmt = value_fmt
self.set_value(value)
@@ -996,8 +1191,12 @@ class DividerField(NoInputField):
self.txt = self.value_fmt % (value)
@overrides(BaseField)
- def render(self, screen, row, active=False, focused=False, col=0, width=None, **kwargs):
- util.safe_curs_set(util.Curser.INVISIBLE) # Make cursor invisible when text field is active
+ def render(
+ self, screen, row, active=False, focused=False, col=0, width=None, **kwargs
+ ):
+ util.safe_curs_set(
+ util.Curser.INVISIBLE
+ ) # Make cursor invisible when text field is active
fmt = self.build_fmt_string(focused, active)
self.fmt_keys['msg'] = self.txt
if self.fill_width:
diff --git a/deluge/ui/console/widgets/inputpane.py b/deluge/ui/console/widgets/inputpane.py
index 2aba998fd..097a6cb8d 100644
--- a/deluge/ui/console/widgets/inputpane.py
+++ b/deluge/ui/console/widgets/inputpane.py
@@ -16,9 +16,21 @@ import logging
from deluge.decorators import overrides
from deluge.ui.console.modes.basemode import InputKeyHandler, move_cursor
from deluge.ui.console.utils import curses_util as util
-from deluge.ui.console.widgets.fields import (CheckedInput, CheckedPlusInput, ComboInput, DividerField, FloatSpinInput,
- Header, InfoField, IntSpinInput, NoInputField, SelectInput, TextArea,
- TextField, TextInput)
+from deluge.ui.console.widgets.fields import (
+ CheckedInput,
+ CheckedPlusInput,
+ ComboInput,
+ DividerField,
+ FloatSpinInput,
+ Header,
+ InfoField,
+ IntSpinInput,
+ NoInputField,
+ SelectInput,
+ TextArea,
+ TextField,
+ TextInput,
+)
try:
import curses
@@ -29,11 +41,18 @@ log = logging.getLogger(__name__)
class BaseInputPane(InputKeyHandler):
-
def __init__(
- self, mode, allow_rearrange=False, immediate_action=False, set_first_input_active=True,
- border_off_west=0, border_off_north=0, border_off_east=0, border_off_south=0,
- active_wrap=False, **kwargs
+ self,
+ mode,
+ allow_rearrange=False,
+ immediate_action=False,
+ set_first_input_active=True,
+ border_off_west=0,
+ border_off_north=0,
+ border_off_east=0,
+ border_off_south=0,
+ active_wrap=False,
+ **kwargs
):
InputKeyHandler.__init__(self)
self.inputs = []
@@ -54,7 +73,9 @@ class BaseInputPane(InputKeyHandler):
if not hasattr(self, 'visible_content_pane_height'):
log.error(
'The class "%s" does not have the attribute "%s" required by super class "%s"',
- self.__class__.__name__, 'visible_content_pane_height', BaseInputPane.__name__,
+ self.__class__.__name__,
+ 'visible_content_pane_height',
+ BaseInputPane.__name__,
)
raise AttributeError('visible_content_pane_height')
@@ -87,9 +108,12 @@ class BaseInputPane(InputKeyHandler):
continue
if e.name == input_element.name:
import traceback
+
log.warning(
'Input element with name "%s" already exists in input pane (%s):\n%s',
- input_element.name, e, ''.join(traceback.format_stack(limit=5)),
+ input_element.name,
+ e,
+ ''.join(traceback.format_stack(limit=5)),
)
return
@@ -106,7 +130,9 @@ class BaseInputPane(InputKeyHandler):
return self._add_input(InfoField(self, name, label, value))
def add_text_field(self, name, message, selectable=True, col='+1', **kwargs):
- return self._add_input(TextField(self, name, message, selectable=selectable, col=col, **kwargs))
+ return self._add_input(
+ TextField(self, name, message, selectable=selectable, col=col, **kwargs)
+ )
def add_text_area(self, name, message, **kwargs):
return self._add_input(TextArea(self, name, message, **kwargs))
@@ -123,28 +149,52 @@ class BaseInputPane(InputKeyHandler):
:param value: initial value of the field
:param complete: should completion be run when tab is hit and this field is active
"""
- return self._add_input(TextInput(
- self, name, message, self.move, self.visible_content_pane_width, value,
- col=col, **kwargs
- ))
+ return self._add_input(
+ TextInput(
+ self,
+ name,
+ message,
+ self.move,
+ self.visible_content_pane_width,
+ value,
+ col=col,
+ **kwargs
+ )
+ )
def add_select_input(self, name, message, opts, vals, default_index=0, **kwargs):
- return self._add_input(SelectInput(self, name, message, opts, vals, default_index, **kwargs))
+ return self._add_input(
+ SelectInput(self, name, message, opts, vals, default_index, **kwargs)
+ )
def add_checked_input(self, name, message, checked=False, col='+1', **kwargs):
- return self._add_input(CheckedInput(self, name, message, checked=checked, col=col, **kwargs))
+ return self._add_input(
+ CheckedInput(self, name, message, checked=checked, col=col, **kwargs)
+ )
- def add_checkedplus_input(self, name, message, child, checked=False, col='+1', **kwargs):
- return self._add_input(CheckedPlusInput(self, name, message, child, checked=checked, col=col, **kwargs))
+ def add_checkedplus_input(
+ self, name, message, child, checked=False, col='+1', **kwargs
+ ):
+ return self._add_input(
+ CheckedPlusInput(
+ self, name, message, child, checked=checked, col=col, **kwargs
+ )
+ )
def add_float_spin_input(self, name, message, value=0.0, col='+1', **kwargs):
- return self._add_input(FloatSpinInput(self, name, message, self.move, value, col=col, **kwargs))
+ return self._add_input(
+ FloatSpinInput(self, name, message, self.move, value, col=col, **kwargs)
+ )
def add_int_spin_input(self, name, message, value=0, col='+1', **kwargs):
- return self._add_input(IntSpinInput(self, name, message, self.move, value, col=col, **kwargs))
+ return self._add_input(
+ IntSpinInput(self, name, message, self.move, value, col=col, **kwargs)
+ )
def add_combo_input(self, name, message, choices, col='+1', **kwargs):
- return self._add_input(ComboInput(self, name, message, choices, col=col, **kwargs))
+ return self._add_input(
+ ComboInput(self, name, message, choices, col=col, **kwargs)
+ )
@overrides(InputKeyHandler)
def handle_read(self, c):
@@ -153,7 +203,9 @@ class BaseInputPane(InputKeyHandler):
ret = self.inputs[self.active_input].handle_read(c)
if ret != util.ReadState.IGNORED:
if self.immediate_action:
- self.immediate_action_cb(state_changed=False if ret == util.ReadState.READ else True)
+ self.immediate_action_cb(
+ state_changed=False if ret == util.ReadState.READ else True
+ )
return ret
ret = util.ReadState.READ
@@ -174,7 +226,9 @@ class BaseInputPane(InputKeyHandler):
self.lineoff = max(self.lineoff - 1, 0)
elif c == util.KEY_ALT_AND_ARROW_DOWN:
tot_height = self.get_content_height()
- self.lineoff = min(self.lineoff + 1, tot_height - self.visible_content_pane_height)
+ self.lineoff = min(
+ self.lineoff + 1, tot_height - self.visible_content_pane_height
+ )
elif c == util.KEY_CTRL_AND_ARROW_UP:
if not self.allow_rearrange:
return ret
@@ -200,7 +254,11 @@ class BaseInputPane(InputKeyHandler):
for i, ipt in enumerate(self.inputs):
if not ipt.has_input():
continue
- vals[ipt.name] = {'value': ipt.get_value(), 'order': i, 'active': self.active_input == i}
+ vals[ipt.name] = {
+ 'value': ipt.get_value(),
+ 'order': i,
+ 'active': self.active_input == i,
+ }
return vals
def immediate_action_cb(self, state_changed=True):
@@ -246,9 +304,15 @@ class BaseInputPane(InputKeyHandler):
cur_sel = next_sel
next_sel = next_move(next_sel, direction, limit)
if cur_sel == next_sel:
- tot_height = self.get_content_height() + self.border_off_north + self.border_off_south
+ tot_height = (
+ self.get_content_height()
+ + self.border_off_north
+ + self.border_off_south
+ )
if direction > 0:
- self.lineoff = min(self.lineoff + 1, tot_height - self.visible_content_pane_height)
+ self.lineoff = min(
+ self.lineoff + 1, tot_height - self.visible_content_pane_height
+ )
else:
self.lineoff = max(self.lineoff - 1, 0)
@@ -285,9 +349,11 @@ class BaseInputPane(InputKeyHandler):
continue
height = self.visible_content_pane_height
if end_row > height + self.lineoff:
- self.lineoff += end_row - (height + self.lineoff) # Correct result depends on paranthesis
+ self.lineoff += end_row - (
+ height + self.lineoff
+ ) # Correct result depends on paranthesis
elif start_row < self.lineoff:
- self.lineoff -= (self.lineoff - start_row)
+ self.lineoff -= self.lineoff - start_row
break
def render_inputs(self, focused=False):
@@ -307,15 +373,23 @@ class BaseInputPane(InputKeyHandler):
if ipt.default_col != -1:
default_col = int(ipt.default_col)
- if isinstance(ipt.default_col, ''.__class__) and ipt.default_col[0] in ['+', '-']:
+ if isinstance(ipt.default_col, ''.__class__) and ipt.default_col[0] in [
+ '+',
+ '-',
+ ]:
col += default_col
cursor_offset += default_col
field_width -= default_col # Increase to col must be reflected here
else:
col = default_col
crow += ipt.render(
- self.screen, crow, width=field_width, active=i == self.active_input,
- focused=focused, col=col, cursor_offset=cursor_offset,
+ self.screen,
+ crow,
+ width=field_width,
+ active=i == self.active_input,
+ focused=focused,
+ col=col,
+ cursor_offset=cursor_offset,
)
if self._cursor_row >= 0:
diff --git a/deluge/ui/console/widgets/popup.py b/deluge/ui/console/widgets/popup.py
index 4553ab257..d588bbb24 100644
--- a/deluge/ui/console/widgets/popup.py
+++ b/deluge/ui/console/widgets/popup.py
@@ -39,7 +39,6 @@ class ALIGN(object):
class PopupsHandler(object):
-
def __init__(self):
self._popups = []
@@ -63,10 +62,17 @@ class PopupsHandler(object):
class Popup(BaseWindow, InputKeyHandler):
-
def __init__(
- self, parent_mode, title, width_req=0, height_req=0, align=ALIGN.DEFAULT,
- close_cb=None, encoding=None, base_popup=None, **kwargs
+ self,
+ parent_mode,
+ title,
+ width_req=0,
+ height_req=0,
+ align=ALIGN.DEFAULT,
+ close_cb=None,
+ encoding=None,
+ base_popup=None,
+ **kwargs
):
"""
Init a new popup. The default constructor will handle sizing and borders and the like.
@@ -120,7 +126,9 @@ class Popup(BaseWindow, InputKeyHandler):
def refresh(self):
self.screen.erase()
height = self.get_content_height()
- self.ensure_content_pane_height(height + self.border_off_north + self.border_off_south)
+ self.ensure_content_pane_height(
+ height + self.border_off_north + self.border_off_south
+ )
BaseInputPane.render_inputs(self, focused=True)
BaseWindow.refresh(self)
@@ -198,9 +206,17 @@ class SelectablePopup(BaseInputPane, Popup):
"""
A popup which will let the user select from some of the lines that are added.
"""
+
def __init__(
- self, parent_mode, title, selection_cb, close_cb=None, input_cb=None,
- allow_rearrange=False, immediate_action=False, **kwargs
+ self,
+ parent_mode,
+ title,
+ selection_cb,
+ close_cb=None,
+ input_cb=None,
+ allow_rearrange=False,
+ immediate_action=False,
+ **kwargs
):
"""
Args:
@@ -215,7 +231,9 @@ class SelectablePopup(BaseInputPane, Popup):
"""
Popup.__init__(self, parent_mode, title, close_cb=close_cb, **kwargs)
- kwargs.update({'allow_rearrange': allow_rearrange, 'immediate_action': immediate_action})
+ kwargs.update(
+ {'allow_rearrange': allow_rearrange, 'immediate_action': immediate_action}
+ )
BaseInputPane.__init__(self, self, **kwargs)
self.selection_cb = selection_cb
self.input_cb = input_cb
@@ -240,8 +258,15 @@ class SelectablePopup(BaseInputPane, Popup):
self.active_input = index
def add_line(
- self, name, string, use_underline=True, cb_arg=None, foreground=None, selectable=True,
- selected=False, **kwargs
+ self,
+ name,
+ string,
+ use_underline=True,
+ cb_arg=None,
+ foreground=None,
+ selectable=True,
+ selected=False,
+ **kwargs
):
hotkey = None
self.cb_arg[name] = cb_arg
@@ -249,7 +274,13 @@ class SelectablePopup(BaseInputPane, Popup):
udx = string.find('_')
if udx >= 0:
hotkey = string[udx].lower()
- string = string[:udx] + '{!+underline!}' + string[udx + 1] + '{!-underline!}' + string[udx + 2:]
+ string = (
+ string[:udx]
+ + '{!+underline!}'
+ + string[udx + 1]
+ + '{!-underline!}'
+ + string[udx + 2 :]
+ )
kwargs['selectable'] = selectable
if foreground:
@@ -299,14 +330,25 @@ class MessagePopup(Popup, BaseInputPane):
"""
Popup that just displays a message
"""
+
def __init__(
- self, parent_mode, title, message, align=ALIGN.DEFAULT,
- height_req=0.75, width_req=0.5, **kwargs
+ self,
+ parent_mode,
+ title,
+ message,
+ align=ALIGN.DEFAULT,
+ height_req=0.75,
+ width_req=0.5,
+ **kwargs
):
self.message = message
Popup.__init__(
- self, parent_mode, title, align=align,
- height_req=height_req, width_req=width_req,
+ self,
+ parent_mode,
+ title,
+ align=align,
+ height_req=height_req,
+ width_req=width_req,
)
BaseInputPane.__init__(self, self, immediate_action=True, **kwargs)
lns = format_utils.wrap_string(self.message, self.width - 3, 3, True)
@@ -327,7 +369,6 @@ class MessagePopup(Popup, BaseInputPane):
class InputPopup(Popup, BaseInputPane):
-
def __init__(self, parent_mode, title, **kwargs):
Popup.__init__(self, parent_mode, title, **kwargs)
BaseInputPane.__init__(self, self, **kwargs)
diff --git a/deluge/ui/console/widgets/sidebar.py b/deluge/ui/console/widgets/sidebar.py
index 410d92216..cc237174d 100644
--- a/deluge/ui/console/widgets/sidebar.py
+++ b/deluge/ui/console/widgets/sidebar.py
@@ -29,7 +29,9 @@ class Sidebar(BaseInputPane, BaseWindow):
"""
- def __init__(self, torrentlist, width, height, title=None, allow_resize=False, **kwargs):
+ def __init__(
+ self, torrentlist, width, height, title=None, allow_resize=False, **kwargs
+ ):
BaseWindow.__init__(self, title, width, height, posy=1)
BaseInputPane.__init__(self, self, immediate_action=True, **kwargs)
self.parent = torrentlist
@@ -49,7 +51,7 @@ class Sidebar(BaseInputPane, BaseWindow):
elif c == curses.KEY_DOWN:
self.move_active_down(1)
elif self.allow_resize and c in [ord('+'), ord('-')]:
- width = self.visible_content_pane_width + (1 if c == ord('+') else - 1)
+ width = self.visible_content_pane_width + (1 if c == ord('+') else -1)
self.on_resize(width)
else:
return BaseInputPane.handle_read(self, c)
@@ -61,14 +63,18 @@ class Sidebar(BaseInputPane, BaseWindow):
@overrides(BaseWindow)
def refresh(self):
height = self.get_content_height()
- self.ensure_content_pane_height(height + self.border_off_north + self.border_off_south)
+ self.ensure_content_pane_height(
+ height + self.border_off_north + self.border_off_south
+ )
BaseInputPane.render_inputs(self, focused=self.has_focus())
BaseWindow.refresh(self)
def _refresh(self):
self.screen.erase()
height = self.get_content_height()
- self.ensure_content_pane_height(height + self.border_off_north + self.border_off_south)
+ self.ensure_content_pane_height(
+ height + self.border_off_north + self.border_off_south
+ )
BaseInputPane.render_inputs(self, focused=True)
BaseWindow.refresh(self)
diff --git a/deluge/ui/console/widgets/statusbars.py b/deluge/ui/console/widgets/statusbars.py
index e1d9c4ccf..fcf4f2f41 100644
--- a/deluge/ui/console/widgets/statusbars.py
+++ b/deluge/ui/console/widgets/statusbars.py
@@ -100,7 +100,9 @@ class StatusBars(component.Component):
self.bottombar += ' D: {!white,blue!}%s{!status!}' % self.download
if self.config['max_download_speed'] > -1:
- self.bottombar += ' (%s ' % self.config['max_download_speed'] + _('KiB/s') + ')'
+ self.bottombar += (
+ ' (%s ' % self.config['max_download_speed'] + _('KiB/s') + ')'
+ )
if self.upload != '0.0 KiB':
self.bottombar += ' U: {!green,blue,bold!}%s{!status!}' % self.upload
@@ -108,7 +110,9 @@ class StatusBars(component.Component):
self.bottombar += ' U: {!white,blue!}%s{!status!}' % self.upload
if self.config['max_upload_speed'] > -1:
- self.bottombar += ' (%s ' % self.config['max_upload_speed'] + _('KiB/s') + ')'
+ self.bottombar += (
+ ' (%s ' % self.config['max_upload_speed'] + _('KiB/s') + ')'
+ )
if self.config['dht']:
self.bottombar += ' ' + _('DHT') + ': {!white,blue!}%s{!status!}' % self.dht
diff --git a/deluge/ui/console/widgets/window.py b/deluge/ui/console/widgets/window.py
index eeb0de4e5..2ef35281e 100644
--- a/deluge/ui/console/widgets/window.py
+++ b/deluge/ui/console/widgets/window.py
@@ -28,6 +28,7 @@ class BaseWindow(object):
"""
BaseWindow creates a curses screen to be used for showing panels and popup dialogs
"""
+
def __init__(self, title, width, height, posy=0, posx=0, encoding=None):
"""
Args:
@@ -42,6 +43,7 @@ class BaseWindow(object):
self.posy, self.posx = posy, posx
if encoding is None:
from deluge import component
+
encoding = component.get('ConsoleUI').encoding
self.encoding = encoding
@@ -117,7 +119,9 @@ class BaseWindow(object):
if content_height <= self.visible_content_pane_height:
return
- percent_scroll = float(self.lineoff) / (content_height - self.visible_content_pane_height)
+ percent_scroll = float(self.lineoff) / (
+ content_height - self.visible_content_pane_height
+ )
indicator_row = int(self.visible_content_pane_height * percent_scroll) + 1
# Never greater than height
@@ -125,8 +129,13 @@ class BaseWindow(object):
indicator_col = self.width + 1
add_string(
- indicator_row, '{!red,black,bold!}#', screen, self.encoding,
- col=indicator_col, pad=False, trim=False,
+ indicator_row,
+ '{!red,black,bold!}#',
+ screen,
+ self.encoding,
+ col=indicator_col,
+ pad=False,
+ trim=False,
)
def refresh(self):
@@ -136,7 +145,13 @@ class BaseWindow(object):
if self.title:
toff = max(1, (self.width // 2) - (len(self.title) // 2))
- self.add_string(0, '{!white,black,bold!}%s' % self.title, scr=self.outer_screen, col=toff, pad=False)
+ self.add_string(
+ 0,
+ '{!white,black,bold!}%s' % self.title,
+ scr=self.outer_screen,
+ col=toff,
+ pad=False,
+ )
self.draw_scroll_indicator(self.outer_screen)
self.outer_screen.noutrefresh()
@@ -151,10 +166,20 @@ class BaseWindow(object):
smincol = self.posx + 1
smaxrow = height + self.posy
smaxcol = width + self.posx
- self.screen.noutrefresh(pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol)
+ self.screen.noutrefresh(
+ pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol
+ )
except curses.error as ex:
import traceback
+
log.warning(
'Error on screen.noutrefresh(%s, %s, %s, %s, %s, %s) Error: %s\nStack: %s',
- pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol, ex, ''.join(traceback.format_stack()),
+ pminrow,
+ pmincol,
+ sminrow,
+ smincol,
+ smaxrow,
+ smaxcol,
+ ex,
+ ''.join(traceback.format_stack()),
)
diff --git a/deluge/ui/coreconfig.py b/deluge/ui/coreconfig.py
index 0462d098a..ed6b614a2 100644
--- a/deluge/ui/coreconfig.py
+++ b/deluge/ui/coreconfig.py
@@ -25,7 +25,10 @@ class CoreConfig(component.Component):
def on_configvaluechanged_event(key, value):
self.config[key] = value
- client.register_event_handler('ConfigValueChangedEvent', on_configvaluechanged_event)
+
+ client.register_event_handler(
+ 'ConfigValueChangedEvent', on_configvaluechanged_event
+ )
def start(self):
def on_get_config(config):
diff --git a/deluge/ui/gtkui/__init__.py b/deluge/ui/gtkui/__init__.py
index 4a5f4e040..c57c468f0 100644
--- a/deluge/ui/gtkui/__init__.py
+++ b/deluge/ui/gtkui/__init__.py
@@ -22,7 +22,9 @@ class Gtk(UI):
cmd_description = """GTK-based graphical user interface"""
def __init__(self, *args, **kwargs):
- super(Gtk, self).__init__('gtk', *args, description='Starts the Deluge GTK+ interface', **kwargs)
+ super(Gtk, self).__init__(
+ 'gtk', *args, description='Starts the Deluge GTK+ interface', **kwargs
+ )
group = self.parser.add_argument_group(_('GTK Options'))
group.add_argument(
@@ -32,7 +34,7 @@ class Gtk(UI):
default=None,
help=_(
'Add one or more torrent files, torrent URLs or magnet URIs'
- ' to a currently running Deluge GTK instance',
+ ' to a currently running Deluge GTK instance'
),
)
diff --git a/deluge/ui/gtkui/aboutdialog.py b/deluge/ui/gtkui/aboutdialog.py
index 355f8f9d3..abb3135f1 100644
--- a/deluge/ui/gtkui/aboutdialog.py
+++ b/deluge/ui/gtkui/aboutdialog.py
@@ -24,234 +24,797 @@ class AboutDialog(object):
self.about.set_position(gtk.WIN_POS_CENTER)
self.about.set_program_name(_('Deluge'))
if windows_check():
+
def url_hook(dialog, url):
"""Url hook for Windows OS which has no default browser."""
open_url_in_browser(url)
return True
+
self.about.connect('activate-link', url_hook)
version = get_version()
self.about.set_copyright(
- _('Copyright %(year_start)s-%(year_end)s Deluge Team') % {'year_start': 2007, 'year_end': 2015},
+ _('Copyright %(year_start)s-%(year_end)s Deluge Team')
+ % {'year_start': 2007, 'year_end': 2015}
)
self.about.set_comments(
- _('A peer-to-peer file sharing program\nutilizing the BitTorrent protocol.') +
- '\n\n' + _('Client:') + ' %s\n' % version,
+ _('A peer-to-peer file sharing program\nutilizing the BitTorrent protocol.')
+ + '\n\n'
+ + _('Client:')
+ + ' %s\n' % version
)
self.about.set_version(version)
- self.about.set_authors([
- _('Current Developers:'), 'Andrew Resch', 'Damien Churchill',
- 'John Garland', 'Calum Lind', '', 'libtorrent (libtorrent.org):',
- 'Arvid Norberg', '', _('Past Developers or Contributors:'),
- 'Zach Tibbitts', 'Alon Zakai', 'Marcos Mobley', 'Alex Dedul',
- 'Sadrul Habib Chowdhury', 'Ido Abramovich', 'Martijn Voncken',
- ])
+ self.about.set_authors(
+ [
+ _('Current Developers:'),
+ 'Andrew Resch',
+ 'Damien Churchill',
+ 'John Garland',
+ 'Calum Lind',
+ '',
+ 'libtorrent (libtorrent.org):',
+ 'Arvid Norberg',
+ '',
+ _('Past Developers or Contributors:'),
+ 'Zach Tibbitts',
+ 'Alon Zakai',
+ 'Marcos Mobley',
+ 'Alex Dedul',
+ 'Sadrul Habib Chowdhury',
+ 'Ido Abramovich',
+ 'Martijn Voncken',
+ ]
+ )
self.about.set_artists(['Andrew Wedderburn', 'Andrew Resch'])
- self.about.set_translator_credits('\n'.join([
- 'Aaron Wang Shi', 'abbigss', 'ABCdatos', 'Abcx', 'Actam', 'Adam',
- 'adaminikisi', 'adi_oporanu', 'Adrian Goll', 'afby', 'Ahmades',
- 'Ahmad Farghal', 'Ahmad Gharbeia أحمد غربية', 'akira', 'Aki Sivula',
- 'Alan Pepelko', 'Alberto', 'Alberto Ferrer', 'alcatr4z', 'AlckO',
- 'Aleksej Korgenkov', 'Alessio Treglia', 'Alexander Ilyashov',
- 'Alexander Matveev', 'Alexander Saltykov', 'Alexander Taubenkorb',
- 'Alexander Telenga', 'Alexander Yurtsev', 'Alexandre Martani',
- 'Alexandre Rosenfeld', 'Alexandre Sapata Carbonell',
- 'Alexey Osipov', 'Alin Claudiu Radut', 'allah', 'AlSim',
- 'Alvaro Carrillanca P.', 'A.Matveev', 'Andras Hipsag',
- 'András Kárász', 'Andrea Ratto', 'Andreas Johansson', 'Andreas Str',
- 'André F. Oliveira', 'AndreiF', 'andrewh', 'Angel Guzman Maeso',
- 'Aníbal Deboni Neto', 'animarval', 'Antonio Cono', 'antoniojreyes',
- 'Anton Shestakov', 'Anton Yakutovich', 'antou',
- 'Arkadiusz Kalinowski', 'Artin', 'artir', 'Astur',
- 'Athanasios Lefteris', 'Athmane MOKRAOUI (ButterflyOfFire)',
- 'Augusta Carla Klug', 'Avoledo Marco', 'axaard', 'AxelRafn',
- 'Axezium', 'Ayont', 'b3rx', 'Bae Taegil', 'Bajusz Tamás',
- "Balaam's Miracle", 'Ballestein', 'Bent Ole Fosse', 'berto89',
- 'bigx', 'Bjorn Inge Berg', 'blackbird', 'Blackeyed', 'blackmx',
- 'BlueSky', 'Blutheo', 'bmhm', 'bob00work', 'boenki',
- 'Bogdan Bădic-Spătariu', 'bonpu', 'Boone', 'boss01',
- 'Branislav Jovanović', 'bronze', 'brownie', 'Brus46', 'bumper',
- 'butely', 'BXCracer', 'c0nfidencal', 'Can Kaya',
- 'Carlos Alexandro Becker', 'cassianoleal', 'Cédric.h',
- 'César Rubén', 'chaoswizard', 'Chen Tao', 'chicha',
- 'Chien Cheng Wei', 'Christian Kopac', 'Christian Widell',
- 'Christoffer Brodd-Reijer', 'christooss', 'CityAceE', 'Clopy',
- 'Clusty', 'cnu', 'Commandant', 'Constantinos Koniaris', 'Coolmax',
- 'cosmix', 'Costin Chirvasuta', 'CoVaLiDiTy', 'cow_2001',
- 'Crispin Kirchner', 'crom', 'Cruster', 'Cybolic', 'Dan Bishop',
- 'Danek', 'Dani', 'Daniel Demarco', 'Daniel Ferreira',
- 'Daniel Frank', 'Daniel Holm', 'Daniel Høyer Iversen',
- 'Daniel Marynicz', 'Daniel Nylander', 'Daniel Patriche',
- 'Daniel Schildt', 'Daniil Sorokin', 'Dante Díaz', 'Daria Michalska',
- 'DarkenCZ', 'Darren', 'Daspah', 'David Eurenius', 'davidhjelm',
- 'David Machakhelidze', 'Dawid Dziurdzia', 'Daya Adianto ', 'dcruz',
- 'Deady', 'Dereck Wonnacott', 'Devgru', 'Devid Antonio Filoni'
- 'DevilDogTG', 'di0rz`', 'Dialecti Valsamou', 'Diego Medeiros',
- 'Dkzoffy', 'Dmitrij D. Czarkoff', 'Dmitriy Geels',
- 'Dmitry Olyenyov', 'Dominik Kozaczko', 'Dominik Lübben', 'doomster',
- 'Dorota Król', 'Doyen Philippe', 'Dread Knight', 'DreamSonic',
- 'duan', 'Duong Thanh An', 'DvoglavaZver', 'dwori', 'dylansmrjones',
- 'Ebuntor', 'Edgar Alejandro Jarquin Flores', 'Eetu', 'ekerazha',
- 'Elias Julkunen', 'elparia', 'Emberke', 'Emiliano Goday Caneda',
- 'EndelWar', 'eng.essam', 'enubuntu', 'ercangun', 'Erdal Ronahi',
- 'ergin üresin', 'Eric', 'Éric Lassauge', 'Erlend Finvåg', 'Errdil',
- 'ethan shalev', 'Evgeni Spasov', 'ezekielnin', 'Fabian Ordelmans',
- 'Fabio Mazanatti', 'Fábio Nogueira', 'FaCuZ', 'Felipe Lerena',
- 'Fernando Pereira', 'fjetland', 'Florian Schäfer', 'FoBoS', 'Folke',
- 'Force', 'fosk', 'fragarray', 'freddeg', 'Frédéric Perrin',
- 'Fredrik Kilegran', 'FreeAtMind', 'Fulvio Ciucci', 'Gabor Kelemen',
- 'Galatsanos Panagiotis', 'Gaussian', 'gdevitis', 'Georg Brzyk',
- 'George Dumitrescu', 'Georgi Arabadjiev', 'Georg Sieber',
- 'Gerd Radecke', 'Germán Heusdens', 'Gianni Vialetto',
- 'Gigih Aji Ibrahim', 'Giorgio Wicklein', 'Giovanni Rapagnani',
- 'Giuseppe', 'gl', 'glen', 'granjerox', 'Green Fish', 'greentea',
- 'Greyhound', 'G. U.', 'Guillaume BENOIT', 'Guillaume Pelletier',
- 'Gustavo Henrique Klug', 'gutocarvalho', 'Guybrush88',
- 'Hans Rødtang', 'HardDisk', 'Hargas Gábor',
- 'Heitor Thury Barreiros Barbosa', 'helios91940', 'helix84',
- 'Helton Rodrigues', 'Hendrik Luup', 'Henrique Ferreiro',
- 'Henry Goury-Laffont', 'Hezy Amiel', 'hidro', 'hoball', 'hokten',
- 'Holmsss', 'hristo.num', 'Hubert Życiński', 'Hyo', 'Iarwain', 'ibe',
- 'ibear', 'Id2ndR', 'Igor Zubarev', 'IKON (Ion)', 'imen',
- 'Ionuț Jula', 'Isabelle STEVANT', 'István Nyitrai', 'Ivan Petrovic',
- 'Ivan Prignano', 'IvaSerge', 'jackmc', 'Jacks0nxD', 'Jack Shen',
- 'Jacky Yeung', 'Jacques Stadler', 'Janek Thomaschewski', 'Jan Kaláb',
- 'Jan Niklas Hasse', 'Jasper Groenewegen', 'Javi Rodríguez',
- 'Jayasimha (ಜಯಸಿಂಹ)', 'jeannich', 'Jeff Bailes', 'Jesse Zilstorff',
- 'Joan Duran', 'João Santos', 'Joar Bagge', 'Joe Anderson',
- 'Joel Calado', 'Johan Linde', 'John Garland', 'Jojan', 'jollyr0ger',
- 'Jonas Bo Grimsgaard', 'Jonas Granqvist', 'Jonas Slivka',
- 'Jonathan Zeppettini', 'Jørgen', 'Jørgen Tellnes', 'josé',
- 'José Geraldo Gouvêa', 'José Iván León Islas', 'José Lou C.',
- 'Jose Sun', 'Jr.', 'Jukka Kauppinen', 'Julián Alarcón',
- 'julietgolf', 'Jusic', 'Justzupi', 'Kaarel', 'Kai Thomsen',
- 'Kalman Tarnay', 'Kamil Páral', 'Kane_F', 'kaotiks@gmail.com',
- 'Kateikyoushii', 'kaxhinaz', 'Kazuhiro NISHIYAMA', 'Kerberos',
- 'Keresztes Ákos', 'kevintyk', 'kiersie', 'Kimbo^', 'Kim Lübbe',
- 'kitzOgen', 'Kjetil Rydland', 'kluon', 'kmikz', 'Knedlyk',
- 'koleoptero', 'Kőrösi Krisztián', 'Kouta', 'Krakatos',
- 'Krešo Kunjas', 'kripken', 'Kristaps', 'Kristian Øllegaard',
- 'Kristoffer Egil Bonarjee', 'Krzysztof Janowski',
- 'Krzysztof Zawada', 'Larry Wei Liu', 'laughterwym', 'Laur Mõtus',
- 'lazka', 'leandrud', 'lê bình', 'Le Coz Florent', 'Leo', 'liorda',
- 'LKRaider', 'LoLo_SaG', 'Long Tran', 'Lorenz', 'Low Kian Seong',
- 'Luca Andrea Rossi', 'Luca Ferretti', 'Lucky LIX', 'Luis Gomes',
- 'Luis Reis', 'Łukasz Wyszyński', 'luojie-dune', 'maaark',
- 'Maciej Chojnacki', 'Maciej Meller', 'Mads Peter Rommedahl',
- 'Major Kong', 'Malaki', 'malde', 'Malte Lenz', 'Mantas Kriaučiūnas',
- 'Mara Sorella', 'Marcin', 'Marcin Falkiewicz', 'marcobra',
- 'Marco da Silva', 'Marco de Moulin', 'Marco Rodrigues', 'Marcos',
- 'Marcos Escalier', 'Marcos Mobley', 'Marcus Ekstrom',
- 'Marek Dębowski', 'Mário Buči', 'Mario Munda', 'Marius Andersen',
- 'Marius Hudea', 'Marius Mihai', 'Mariusz Cielecki',
- 'Mark Krapivner', 'marko-markovic', 'Markus Brummer',
- 'Markus Sutter', 'Martin', 'Martin Dybdal', 'Martin Iglesias',
- 'Martin Lettner', 'Martin Pihl', 'Masoud Kalali', 'mat02',
- 'Matej Urbančič', 'Mathias-K', 'Mathieu Arès',
- 'Mathieu D. (MatToufoutu)', 'Mathijs', 'Matrik', 'Matteo Renzulli',
- 'Matteo Settenvini', 'Matthew Gadd', 'Matthias Benkard',
- 'Matthias Mailänder', 'Mattias Ohlsson', 'Mauro de Carvalho',
- 'Max Molchanov', 'Me', 'MercuryCC', 'Mert Bozkurt', 'Mert Dirik',
- 'MFX', 'mhietar', 'mibtha', 'Michael Budde', 'Michael Kaliszka',
- 'Michalis Makaronides', 'Michał Tokarczyk', 'Miguel Pires da Rosa',
- 'Mihai Capotă', 'Miika Metsälä', 'Mikael Fernblad', 'Mike Sierra',
- 'mikhalek', 'Milan Prvulović', 'Milo Casagrande', 'Mindaugas',
- 'Miroslav Matejaš', 'misel', 'mithras', 'Mitja Pagon', 'M.Kitchen',
- 'Mohamed Magdy', 'moonkey', 'MrBlonde', 'muczy', 'Münir Ekinci',
- 'Mustafa Temizel', 'mvoncken', 'Mytonn', 'NagyMarton', 'neaion',
- 'Neil Lin', 'Nemo', 'Nerijus Arlauskas', 'Nicklas Larsson',
- 'Nicolaj Wyke', 'Nicola Piovesan', 'Nicolas Sabatier',
- 'Nicolas Velin', 'Nightfall', 'NiKoB', 'Nikolai M. Riabov',
- 'Niko_Thien', 'niska', 'Nithir', 'noisemonkey', 'nomemohes',
- 'nosense', 'null', 'Nuno Estêvão', 'Nuno Santos', 'nxxs', 'nyo',
- 'obo', 'Ojan', 'Olav Andreas Lindekleiv', 'oldbeggar',
- 'Olivier FAURAX', 'orphe', 'osantana', 'Osman Tosun', 'OssiR',
- 'otypoks', 'ounn', 'Oz123', 'Özgür BASKIN', 'Pablo Carmona A.',
- 'Pablo Ledesma', 'Pablo Navarro Castillo', 'Paco Molinero',
- 'Pål-Eivind Johnsen', 'pano', 'Paolo Naldini', 'Paracelsus',
- 'Patryk13_03', 'Patryk Skorupa', 'PattogoTehen', 'Paul Lange',
- 'Pavcio', 'Paweł Wysocki', 'Pedro Brites Moita',
- 'Pedro Clemente Pereira Neto', 'Pekka "PEXI" Niemistö', 'Penegal',
- 'Penzo', 'perdido', 'Peter Kotrcka', 'Peter Skov',
- 'Peter Van den Bosch', 'Petter Eklund', 'Petter Viklund',
- 'phatsphere', 'Phenomen', 'Philipi', 'Philippides Homer', 'phoenix',
- 'pidi', 'Pierre Quillery', 'Pierre Rudloff', 'Pierre Slamich',
- 'Pietrao', 'Piotr Strębski', 'Piotr Wicijowski', 'Pittmann Tamás',
- 'Playmolas', 'Prescott', 'Prescott_SK', 'pronull',
- 'Przemysław Kulczycki', 'Pumy', 'pushpika', 'PY', 'qubicllj',
- 'r21vo', 'Rafał Barański', 'rainofchaos', 'Rajbir', 'ras0ir', 'Rat',
- 'rd1381', 'Renato', 'Rene Hennig', 'Rene Pärts', 'Ricardo Duarte',
- 'Richard', 'Robert Hrovat', 'Roberth Sjonøy', 'Robert Lundmark',
- 'Robin Jakobsson', 'Robin Kåveland', 'Rodrigo Donado',
- 'Roel Groeneveld', 'rohmaru', 'Rolf Christensen', 'Rolf Leggewie',
- 'Roni Kantis', 'Ronmi', 'Rostislav Raykov', 'royto', 'RuiAmaro',
- 'Rui Araújo', 'Rui Moura', 'Rune Svendsen', 'Rusna', 'Rytis',
- 'Sabirov Mikhail', 'salseeg', 'Sami Koskinen', 'Samir van de Sand',
- 'Samuel Arroyo Acuña', 'Samuel R. C. Vale', 'Sanel', 'Santi',
- 'Santi Martínez Cantelli', 'Sardan', 'Sargate Kanogan',
- 'Sarmad Jari', 'Saša Bodiroža', 'sat0shi', 'Saulius Pranckevičius',
- 'Savvas Radevic', 'Sebastian Krauß', 'Sebastián Porta', 'Sedir',
- 'Sefa Denizoğlu', 'sekolands', 'Selim Suerkan', 'semsomi',
- 'Sergii Golovatiuk', 'setarcos', 'Sheki', 'Shironeko', 'Shlomil',
- 'silfiriel', 'Simone Tolotti', 'Simone Vendemia', 'sirkubador',
- 'Sławomir Więch', 'slip', 'slyon', 'smoke', 'Sonja', 'spectral',
- 'spin_555', 'spitf1r3', 'Spiziuz', 'Spyros Theodoritsis', 'SqUe',
- 'Squigly', 'srtck', 'Stefan Horning', 'Stefano Maggiolo',
- 'Stefano Roberto Soleti', 'steinberger', 'Stéphane Travostino',
- 'Stephan Klein', 'Steven De Winter', 'Stevie', 'Stian24', 'stylius',
- 'Sukarn Maini', 'Sunjae Park', 'Susana Pereira', 'szymon siglowy',
- 'takercena', 'TAS', 'Taygeto', 'temy4', 'texxxxxx', 'thamood',
- 'Thanos Chatziathanassiou', 'Tharawut Paripaiboon', 'Theodoor',
- 'Théophane Anestis', 'Thor Marius K. Høgås', 'Tiago Silva',
- 'Tiago Sousa', 'Tikkel', 'tim__b', 'Tim Bordemann', 'Tim Fuchs',
- 'Tim Kornhammar', 'Timo', 'Timo Jyrinki', 'Timothy Babych',
- 'TitkosRejtozo', 'Tom', 'Tomas Gustavsson', 'Tomas Valentukevičius',
- 'Tomasz Dominikowski', 'Tomislav Plavčić', 'Tom Mannerhagen',
- 'Tommy Mikkelsen', 'Tom Verdaat', 'Tony Manco',
- 'Tor Erling H. Opsahl', 'Toudi', 'tqm_z', 'Trapanator', 'Tribaal',
- 'Triton', 'TuniX12', 'Tuomo Sipola', 'turbojugend_gr', 'Turtle.net',
- 'twilight', 'tymmej', 'Ulrik', 'Umarzuki Mochlis', 'unikob',
- 'Vadim Gusev', 'Vagi', 'Valentin Bora', 'Valmantas Palikša',
- 'VASKITTU', 'Vassilis Skoullis', 'vetal17', 'vicedo', 'viki',
- 'villads hamann', 'Vincent Garibal', 'Vincent Ortalda', 'vinchi007',
- 'Vinícius de Figueiredo Silva', 'Vinzenz Vietzke', 'virtoo',
- 'virtual_spirit', 'Vitor Caike', 'Vitor Lamas Gatti',
- 'Vladimir Lazic', 'Vladimir Sharshov', 'Wanderlust', 'Wander Nauta',
- 'Ward De Ridder', 'WebCrusader', 'webdr', 'Wentao Tang', 'wilana',
- 'Wilfredo Ernesto Guerrero Campos', 'Wim Champagne', 'World Sucks',
- 'Xabi Ezpeleta', 'Xavi de Moner', 'XavierToo', 'XChesser',
- 'Xiaodong Xu', 'xyb', 'Yaron', 'Yasen Pramatarov', 'YesPoX',
- 'Yuren Ju', 'Yves MATHIEU', 'zekopeko', 'zhuqin', 'Zissan',
- 'Γιάννης Κατσαμπίρης', 'Артём Попов', 'Миша', 'Шаймарданов Максим',
- '蔡查理',
- ]))
+ self.about.set_translator_credits(
+ '\n'.join(
+ [
+ 'Aaron Wang Shi',
+ 'abbigss',
+ 'ABCdatos',
+ 'Abcx',
+ 'Actam',
+ 'Adam',
+ 'adaminikisi',
+ 'adi_oporanu',
+ 'Adrian Goll',
+ 'afby',
+ 'Ahmades',
+ 'Ahmad Farghal',
+ 'Ahmad Gharbeia أحمد غربية',
+ 'akira',
+ 'Aki Sivula',
+ 'Alan Pepelko',
+ 'Alberto',
+ 'Alberto Ferrer',
+ 'alcatr4z',
+ 'AlckO',
+ 'Aleksej Korgenkov',
+ 'Alessio Treglia',
+ 'Alexander Ilyashov',
+ 'Alexander Matveev',
+ 'Alexander Saltykov',
+ 'Alexander Taubenkorb',
+ 'Alexander Telenga',
+ 'Alexander Yurtsev',
+ 'Alexandre Martani',
+ 'Alexandre Rosenfeld',
+ 'Alexandre Sapata Carbonell',
+ 'Alexey Osipov',
+ 'Alin Claudiu Radut',
+ 'allah',
+ 'AlSim',
+ 'Alvaro Carrillanca P.',
+ 'A.Matveev',
+ 'Andras Hipsag',
+ 'András Kárász',
+ 'Andrea Ratto',
+ 'Andreas Johansson',
+ 'Andreas Str',
+ 'André F. Oliveira',
+ 'AndreiF',
+ 'andrewh',
+ 'Angel Guzman Maeso',
+ 'Aníbal Deboni Neto',
+ 'animarval',
+ 'Antonio Cono',
+ 'antoniojreyes',
+ 'Anton Shestakov',
+ 'Anton Yakutovich',
+ 'antou',
+ 'Arkadiusz Kalinowski',
+ 'Artin',
+ 'artir',
+ 'Astur',
+ 'Athanasios Lefteris',
+ 'Athmane MOKRAOUI (ButterflyOfFire)',
+ 'Augusta Carla Klug',
+ 'Avoledo Marco',
+ 'axaard',
+ 'AxelRafn',
+ 'Axezium',
+ 'Ayont',
+ 'b3rx',
+ 'Bae Taegil',
+ 'Bajusz Tamás',
+ "Balaam's Miracle",
+ 'Ballestein',
+ 'Bent Ole Fosse',
+ 'berto89',
+ 'bigx',
+ 'Bjorn Inge Berg',
+ 'blackbird',
+ 'Blackeyed',
+ 'blackmx',
+ 'BlueSky',
+ 'Blutheo',
+ 'bmhm',
+ 'bob00work',
+ 'boenki',
+ 'Bogdan Bădic-Spătariu',
+ 'bonpu',
+ 'Boone',
+ 'boss01',
+ 'Branislav Jovanović',
+ 'bronze',
+ 'brownie',
+ 'Brus46',
+ 'bumper',
+ 'butely',
+ 'BXCracer',
+ 'c0nfidencal',
+ 'Can Kaya',
+ 'Carlos Alexandro Becker',
+ 'cassianoleal',
+ 'Cédric.h',
+ 'César Rubén',
+ 'chaoswizard',
+ 'Chen Tao',
+ 'chicha',
+ 'Chien Cheng Wei',
+ 'Christian Kopac',
+ 'Christian Widell',
+ 'Christoffer Brodd-Reijer',
+ 'christooss',
+ 'CityAceE',
+ 'Clopy',
+ 'Clusty',
+ 'cnu',
+ 'Commandant',
+ 'Constantinos Koniaris',
+ 'Coolmax',
+ 'cosmix',
+ 'Costin Chirvasuta',
+ 'CoVaLiDiTy',
+ 'cow_2001',
+ 'Crispin Kirchner',
+ 'crom',
+ 'Cruster',
+ 'Cybolic',
+ 'Dan Bishop',
+ 'Danek',
+ 'Dani',
+ 'Daniel Demarco',
+ 'Daniel Ferreira',
+ 'Daniel Frank',
+ 'Daniel Holm',
+ 'Daniel Høyer Iversen',
+ 'Daniel Marynicz',
+ 'Daniel Nylander',
+ 'Daniel Patriche',
+ 'Daniel Schildt',
+ 'Daniil Sorokin',
+ 'Dante Díaz',
+ 'Daria Michalska',
+ 'DarkenCZ',
+ 'Darren',
+ 'Daspah',
+ 'David Eurenius',
+ 'davidhjelm',
+ 'David Machakhelidze',
+ 'Dawid Dziurdzia',
+ 'Daya Adianto ',
+ 'dcruz',
+ 'Deady',
+ 'Dereck Wonnacott',
+ 'Devgru',
+ 'Devid Antonio Filoni' 'DevilDogTG',
+ 'di0rz`',
+ 'Dialecti Valsamou',
+ 'Diego Medeiros',
+ 'Dkzoffy',
+ 'Dmitrij D. Czarkoff',
+ 'Dmitriy Geels',
+ 'Dmitry Olyenyov',
+ 'Dominik Kozaczko',
+ 'Dominik Lübben',
+ 'doomster',
+ 'Dorota Król',
+ 'Doyen Philippe',
+ 'Dread Knight',
+ 'DreamSonic',
+ 'duan',
+ 'Duong Thanh An',
+ 'DvoglavaZver',
+ 'dwori',
+ 'dylansmrjones',
+ 'Ebuntor',
+ 'Edgar Alejandro Jarquin Flores',
+ 'Eetu',
+ 'ekerazha',
+ 'Elias Julkunen',
+ 'elparia',
+ 'Emberke',
+ 'Emiliano Goday Caneda',
+ 'EndelWar',
+ 'eng.essam',
+ 'enubuntu',
+ 'ercangun',
+ 'Erdal Ronahi',
+ 'ergin üresin',
+ 'Eric',
+ 'Éric Lassauge',
+ 'Erlend Finvåg',
+ 'Errdil',
+ 'ethan shalev',
+ 'Evgeni Spasov',
+ 'ezekielnin',
+ 'Fabian Ordelmans',
+ 'Fabio Mazanatti',
+ 'Fábio Nogueira',
+ 'FaCuZ',
+ 'Felipe Lerena',
+ 'Fernando Pereira',
+ 'fjetland',
+ 'Florian Schäfer',
+ 'FoBoS',
+ 'Folke',
+ 'Force',
+ 'fosk',
+ 'fragarray',
+ 'freddeg',
+ 'Frédéric Perrin',
+ 'Fredrik Kilegran',
+ 'FreeAtMind',
+ 'Fulvio Ciucci',
+ 'Gabor Kelemen',
+ 'Galatsanos Panagiotis',
+ 'Gaussian',
+ 'gdevitis',
+ 'Georg Brzyk',
+ 'George Dumitrescu',
+ 'Georgi Arabadjiev',
+ 'Georg Sieber',
+ 'Gerd Radecke',
+ 'Germán Heusdens',
+ 'Gianni Vialetto',
+ 'Gigih Aji Ibrahim',
+ 'Giorgio Wicklein',
+ 'Giovanni Rapagnani',
+ 'Giuseppe',
+ 'gl',
+ 'glen',
+ 'granjerox',
+ 'Green Fish',
+ 'greentea',
+ 'Greyhound',
+ 'G. U.',
+ 'Guillaume BENOIT',
+ 'Guillaume Pelletier',
+ 'Gustavo Henrique Klug',
+ 'gutocarvalho',
+ 'Guybrush88',
+ 'Hans Rødtang',
+ 'HardDisk',
+ 'Hargas Gábor',
+ 'Heitor Thury Barreiros Barbosa',
+ 'helios91940',
+ 'helix84',
+ 'Helton Rodrigues',
+ 'Hendrik Luup',
+ 'Henrique Ferreiro',
+ 'Henry Goury-Laffont',
+ 'Hezy Amiel',
+ 'hidro',
+ 'hoball',
+ 'hokten',
+ 'Holmsss',
+ 'hristo.num',
+ 'Hubert Życiński',
+ 'Hyo',
+ 'Iarwain',
+ 'ibe',
+ 'ibear',
+ 'Id2ndR',
+ 'Igor Zubarev',
+ 'IKON (Ion)',
+ 'imen',
+ 'Ionuț Jula',
+ 'Isabelle STEVANT',
+ 'István Nyitrai',
+ 'Ivan Petrovic',
+ 'Ivan Prignano',
+ 'IvaSerge',
+ 'jackmc',
+ 'Jacks0nxD',
+ 'Jack Shen',
+ 'Jacky Yeung',
+ 'Jacques Stadler',
+ 'Janek Thomaschewski',
+ 'Jan Kaláb',
+ 'Jan Niklas Hasse',
+ 'Jasper Groenewegen',
+ 'Javi Rodríguez',
+ 'Jayasimha (ಜಯಸಿಂಹ)',
+ 'jeannich',
+ 'Jeff Bailes',
+ 'Jesse Zilstorff',
+ 'Joan Duran',
+ 'João Santos',
+ 'Joar Bagge',
+ 'Joe Anderson',
+ 'Joel Calado',
+ 'Johan Linde',
+ 'John Garland',
+ 'Jojan',
+ 'jollyr0ger',
+ 'Jonas Bo Grimsgaard',
+ 'Jonas Granqvist',
+ 'Jonas Slivka',
+ 'Jonathan Zeppettini',
+ 'Jørgen',
+ 'Jørgen Tellnes',
+ 'josé',
+ 'José Geraldo Gouvêa',
+ 'José Iván León Islas',
+ 'José Lou C.',
+ 'Jose Sun',
+ 'Jr.',
+ 'Jukka Kauppinen',
+ 'Julián Alarcón',
+ 'julietgolf',
+ 'Jusic',
+ 'Justzupi',
+ 'Kaarel',
+ 'Kai Thomsen',
+ 'Kalman Tarnay',
+ 'Kamil Páral',
+ 'Kane_F',
+ 'kaotiks@gmail.com',
+ 'Kateikyoushii',
+ 'kaxhinaz',
+ 'Kazuhiro NISHIYAMA',
+ 'Kerberos',
+ 'Keresztes Ákos',
+ 'kevintyk',
+ 'kiersie',
+ 'Kimbo^',
+ 'Kim Lübbe',
+ 'kitzOgen',
+ 'Kjetil Rydland',
+ 'kluon',
+ 'kmikz',
+ 'Knedlyk',
+ 'koleoptero',
+ 'Kőrösi Krisztián',
+ 'Kouta',
+ 'Krakatos',
+ 'Krešo Kunjas',
+ 'kripken',
+ 'Kristaps',
+ 'Kristian Øllegaard',
+ 'Kristoffer Egil Bonarjee',
+ 'Krzysztof Janowski',
+ 'Krzysztof Zawada',
+ 'Larry Wei Liu',
+ 'laughterwym',
+ 'Laur Mõtus',
+ 'lazka',
+ 'leandrud',
+ 'lê bình',
+ 'Le Coz Florent',
+ 'Leo',
+ 'liorda',
+ 'LKRaider',
+ 'LoLo_SaG',
+ 'Long Tran',
+ 'Lorenz',
+ 'Low Kian Seong',
+ 'Luca Andrea Rossi',
+ 'Luca Ferretti',
+ 'Lucky LIX',
+ 'Luis Gomes',
+ 'Luis Reis',
+ 'Łukasz Wyszyński',
+ 'luojie-dune',
+ 'maaark',
+ 'Maciej Chojnacki',
+ 'Maciej Meller',
+ 'Mads Peter Rommedahl',
+ 'Major Kong',
+ 'Malaki',
+ 'malde',
+ 'Malte Lenz',
+ 'Mantas Kriaučiūnas',
+ 'Mara Sorella',
+ 'Marcin',
+ 'Marcin Falkiewicz',
+ 'marcobra',
+ 'Marco da Silva',
+ 'Marco de Moulin',
+ 'Marco Rodrigues',
+ 'Marcos',
+ 'Marcos Escalier',
+ 'Marcos Mobley',
+ 'Marcus Ekstrom',
+ 'Marek Dębowski',
+ 'Mário Buči',
+ 'Mario Munda',
+ 'Marius Andersen',
+ 'Marius Hudea',
+ 'Marius Mihai',
+ 'Mariusz Cielecki',
+ 'Mark Krapivner',
+ 'marko-markovic',
+ 'Markus Brummer',
+ 'Markus Sutter',
+ 'Martin',
+ 'Martin Dybdal',
+ 'Martin Iglesias',
+ 'Martin Lettner',
+ 'Martin Pihl',
+ 'Masoud Kalali',
+ 'mat02',
+ 'Matej Urbančič',
+ 'Mathias-K',
+ 'Mathieu Arès',
+ 'Mathieu D. (MatToufoutu)',
+ 'Mathijs',
+ 'Matrik',
+ 'Matteo Renzulli',
+ 'Matteo Settenvini',
+ 'Matthew Gadd',
+ 'Matthias Benkard',
+ 'Matthias Mailänder',
+ 'Mattias Ohlsson',
+ 'Mauro de Carvalho',
+ 'Max Molchanov',
+ 'Me',
+ 'MercuryCC',
+ 'Mert Bozkurt',
+ 'Mert Dirik',
+ 'MFX',
+ 'mhietar',
+ 'mibtha',
+ 'Michael Budde',
+ 'Michael Kaliszka',
+ 'Michalis Makaronides',
+ 'Michał Tokarczyk',
+ 'Miguel Pires da Rosa',
+ 'Mihai Capotă',
+ 'Miika Metsälä',
+ 'Mikael Fernblad',
+ 'Mike Sierra',
+ 'mikhalek',
+ 'Milan Prvulović',
+ 'Milo Casagrande',
+ 'Mindaugas',
+ 'Miroslav Matejaš',
+ 'misel',
+ 'mithras',
+ 'Mitja Pagon',
+ 'M.Kitchen',
+ 'Mohamed Magdy',
+ 'moonkey',
+ 'MrBlonde',
+ 'muczy',
+ 'Münir Ekinci',
+ 'Mustafa Temizel',
+ 'mvoncken',
+ 'Mytonn',
+ 'NagyMarton',
+ 'neaion',
+ 'Neil Lin',
+ 'Nemo',
+ 'Nerijus Arlauskas',
+ 'Nicklas Larsson',
+ 'Nicolaj Wyke',
+ 'Nicola Piovesan',
+ 'Nicolas Sabatier',
+ 'Nicolas Velin',
+ 'Nightfall',
+ 'NiKoB',
+ 'Nikolai M. Riabov',
+ 'Niko_Thien',
+ 'niska',
+ 'Nithir',
+ 'noisemonkey',
+ 'nomemohes',
+ 'nosense',
+ 'null',
+ 'Nuno Estêvão',
+ 'Nuno Santos',
+ 'nxxs',
+ 'nyo',
+ 'obo',
+ 'Ojan',
+ 'Olav Andreas Lindekleiv',
+ 'oldbeggar',
+ 'Olivier FAURAX',
+ 'orphe',
+ 'osantana',
+ 'Osman Tosun',
+ 'OssiR',
+ 'otypoks',
+ 'ounn',
+ 'Oz123',
+ 'Özgür BASKIN',
+ 'Pablo Carmona A.',
+ 'Pablo Ledesma',
+ 'Pablo Navarro Castillo',
+ 'Paco Molinero',
+ 'Pål-Eivind Johnsen',
+ 'pano',
+ 'Paolo Naldini',
+ 'Paracelsus',
+ 'Patryk13_03',
+ 'Patryk Skorupa',
+ 'PattogoTehen',
+ 'Paul Lange',
+ 'Pavcio',
+ 'Paweł Wysocki',
+ 'Pedro Brites Moita',
+ 'Pedro Clemente Pereira Neto',
+ 'Pekka "PEXI" Niemistö',
+ 'Penegal',
+ 'Penzo',
+ 'perdido',
+ 'Peter Kotrcka',
+ 'Peter Skov',
+ 'Peter Van den Bosch',
+ 'Petter Eklund',
+ 'Petter Viklund',
+ 'phatsphere',
+ 'Phenomen',
+ 'Philipi',
+ 'Philippides Homer',
+ 'phoenix',
+ 'pidi',
+ 'Pierre Quillery',
+ 'Pierre Rudloff',
+ 'Pierre Slamich',
+ 'Pietrao',
+ 'Piotr Strębski',
+ 'Piotr Wicijowski',
+ 'Pittmann Tamás',
+ 'Playmolas',
+ 'Prescott',
+ 'Prescott_SK',
+ 'pronull',
+ 'Przemysław Kulczycki',
+ 'Pumy',
+ 'pushpika',
+ 'PY',
+ 'qubicllj',
+ 'r21vo',
+ 'Rafał Barański',
+ 'rainofchaos',
+ 'Rajbir',
+ 'ras0ir',
+ 'Rat',
+ 'rd1381',
+ 'Renato',
+ 'Rene Hennig',
+ 'Rene Pärts',
+ 'Ricardo Duarte',
+ 'Richard',
+ 'Robert Hrovat',
+ 'Roberth Sjonøy',
+ 'Robert Lundmark',
+ 'Robin Jakobsson',
+ 'Robin Kåveland',
+ 'Rodrigo Donado',
+ 'Roel Groeneveld',
+ 'rohmaru',
+ 'Rolf Christensen',
+ 'Rolf Leggewie',
+ 'Roni Kantis',
+ 'Ronmi',
+ 'Rostislav Raykov',
+ 'royto',
+ 'RuiAmaro',
+ 'Rui Araújo',
+ 'Rui Moura',
+ 'Rune Svendsen',
+ 'Rusna',
+ 'Rytis',
+ 'Sabirov Mikhail',
+ 'salseeg',
+ 'Sami Koskinen',
+ 'Samir van de Sand',
+ 'Samuel Arroyo Acuña',
+ 'Samuel R. C. Vale',
+ 'Sanel',
+ 'Santi',
+ 'Santi Martínez Cantelli',
+ 'Sardan',
+ 'Sargate Kanogan',
+ 'Sarmad Jari',
+ 'Saša Bodiroža',
+ 'sat0shi',
+ 'Saulius Pranckevičius',
+ 'Savvas Radevic',
+ 'Sebastian Krauß',
+ 'Sebastián Porta',
+ 'Sedir',
+ 'Sefa Denizoğlu',
+ 'sekolands',
+ 'Selim Suerkan',
+ 'semsomi',
+ 'Sergii Golovatiuk',
+ 'setarcos',
+ 'Sheki',
+ 'Shironeko',
+ 'Shlomil',
+ 'silfiriel',
+ 'Simone Tolotti',
+ 'Simone Vendemia',
+ 'sirkubador',
+ 'Sławomir Więch',
+ 'slip',
+ 'slyon',
+ 'smoke',
+ 'Sonja',
+ 'spectral',
+ 'spin_555',
+ 'spitf1r3',
+ 'Spiziuz',
+ 'Spyros Theodoritsis',
+ 'SqUe',
+ 'Squigly',
+ 'srtck',
+ 'Stefan Horning',
+ 'Stefano Maggiolo',
+ 'Stefano Roberto Soleti',
+ 'steinberger',
+ 'Stéphane Travostino',
+ 'Stephan Klein',
+ 'Steven De Winter',
+ 'Stevie',
+ 'Stian24',
+ 'stylius',
+ 'Sukarn Maini',
+ 'Sunjae Park',
+ 'Susana Pereira',
+ 'szymon siglowy',
+ 'takercena',
+ 'TAS',
+ 'Taygeto',
+ 'temy4',
+ 'texxxxxx',
+ 'thamood',
+ 'Thanos Chatziathanassiou',
+ 'Tharawut Paripaiboon',
+ 'Theodoor',
+ 'Théophane Anestis',
+ 'Thor Marius K. Høgås',
+ 'Tiago Silva',
+ 'Tiago Sousa',
+ 'Tikkel',
+ 'tim__b',
+ 'Tim Bordemann',
+ 'Tim Fuchs',
+ 'Tim Kornhammar',
+ 'Timo',
+ 'Timo Jyrinki',
+ 'Timothy Babych',
+ 'TitkosRejtozo',
+ 'Tom',
+ 'Tomas Gustavsson',
+ 'Tomas Valentukevičius',
+ 'Tomasz Dominikowski',
+ 'Tomislav Plavčić',
+ 'Tom Mannerhagen',
+ 'Tommy Mikkelsen',
+ 'Tom Verdaat',
+ 'Tony Manco',
+ 'Tor Erling H. Opsahl',
+ 'Toudi',
+ 'tqm_z',
+ 'Trapanator',
+ 'Tribaal',
+ 'Triton',
+ 'TuniX12',
+ 'Tuomo Sipola',
+ 'turbojugend_gr',
+ 'Turtle.net',
+ 'twilight',
+ 'tymmej',
+ 'Ulrik',
+ 'Umarzuki Mochlis',
+ 'unikob',
+ 'Vadim Gusev',
+ 'Vagi',
+ 'Valentin Bora',
+ 'Valmantas Palikša',
+ 'VASKITTU',
+ 'Vassilis Skoullis',
+ 'vetal17',
+ 'vicedo',
+ 'viki',
+ 'villads hamann',
+ 'Vincent Garibal',
+ 'Vincent Ortalda',
+ 'vinchi007',
+ 'Vinícius de Figueiredo Silva',
+ 'Vinzenz Vietzke',
+ 'virtoo',
+ 'virtual_spirit',
+ 'Vitor Caike',
+ 'Vitor Lamas Gatti',
+ 'Vladimir Lazic',
+ 'Vladimir Sharshov',
+ 'Wanderlust',
+ 'Wander Nauta',
+ 'Ward De Ridder',
+ 'WebCrusader',
+ 'webdr',
+ 'Wentao Tang',
+ 'wilana',
+ 'Wilfredo Ernesto Guerrero Campos',
+ 'Wim Champagne',
+ 'World Sucks',
+ 'Xabi Ezpeleta',
+ 'Xavi de Moner',
+ 'XavierToo',
+ 'XChesser',
+ 'Xiaodong Xu',
+ 'xyb',
+ 'Yaron',
+ 'Yasen Pramatarov',
+ 'YesPoX',
+ 'Yuren Ju',
+ 'Yves MATHIEU',
+ 'zekopeko',
+ 'zhuqin',
+ 'Zissan',
+ 'Γιάννης Κατσαμπίρης',
+ 'Артём Попов',
+ 'Миша',
+ 'Шаймарданов Максим',
+ '蔡查理',
+ ]
+ )
+ )
self.about.set_wrap_license(True)
- self.about.set_license(_(
- 'This program is free software; you can redistribute it and/or '
- 'modify it under the terms of the GNU General Public License as '
- 'published by the Free Software Foundation; either version 3 of '
- 'the License, or (at your option) any later version. \n\n'
- 'This program '
- 'is distributed in the hope that it will be useful, but WITHOUT '
- 'ANY WARRANTY; without even the implied warranty of '
- 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU '
- 'General Public License for more details. \n\n'
- 'You should have received '
- 'a copy of the GNU General Public License along with this program; '
- 'if not, see <http://www.gnu.org/licenses>. \n\n'
- 'In addition, as a '
- 'special exception, the copyright holders give permission to link '
- 'the code of portions of this program with the OpenSSL library. '
- 'You must obey the GNU General Public License in all respects for '
- 'all of the code used other than OpenSSL. \n\n'
- 'If you modify file(s) '
- 'with this exception, you may extend this exception to your '
- 'version of the file(s), but you are not obligated to do so. If '
- 'you do not wish to do so, delete this exception statement from '
- 'your version. If you delete this exception statement from all '
- 'source files in the program, then also delete it here.',
- ))
+ self.about.set_license(
+ _(
+ 'This program is free software; you can redistribute it and/or '
+ 'modify it under the terms of the GNU General Public License as '
+ 'published by the Free Software Foundation; either version 3 of '
+ 'the License, or (at your option) any later version. \n\n'
+ 'This program '
+ 'is distributed in the hope that it will be useful, but WITHOUT '
+ 'ANY WARRANTY; without even the implied warranty of '
+ 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU '
+ 'General Public License for more details. \n\n'
+ 'You should have received '
+ 'a copy of the GNU General Public License along with this program; '
+ 'if not, see <http://www.gnu.org/licenses>. \n\n'
+ 'In addition, as a '
+ 'special exception, the copyright holders give permission to link '
+ 'the code of portions of this program with the OpenSSL library. '
+ 'You must obey the GNU General Public License in all respects for '
+ 'all of the code used other than OpenSSL. \n\n'
+ 'If you modify file(s) '
+ 'with this exception, you may extend this exception to your '
+ 'version of the file(s), but you are not obligated to do so. If '
+ 'you do not wish to do so, delete this exception statement from '
+ 'your version. If you delete this exception statement from all '
+ 'source files in the program, then also delete it here.'
+ )
+ )
self.about.set_website('http://deluge-torrent.org')
self.about.set_website_label('deluge-torrent.org')
@@ -261,11 +824,11 @@ class AboutDialog(object):
if client.connected():
if not client.is_standalone():
self.about.set_comments(
- self.about.get_comments() + _('Server:') + ' %coreversion%\n',
+ self.about.get_comments() + _('Server:') + ' %coreversion%\n'
)
self.about.set_comments(
- self.about.get_comments() + '\n' + _('libtorrent:') + ' %ltversion%\n',
+ self.about.get_comments() + '\n' + _('libtorrent:') + ' %ltversion%\n'
)
def on_lt_version(result):
diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py
index ff002d019..365d0f301 100644
--- a/deluge/ui/gtkui/addtorrentdialog.py
+++ b/deluge/ui/gtkui/addtorrentdialog.py
@@ -24,7 +24,11 @@ from deluge.configmanager import ConfigManager
from deluge.httpdownloader import download_file
from deluge.ui.client import client
from deluge.ui.common import TorrentInfo
-from deluge.ui.gtkui.common import get_clipboard_text, listview_replace_treestore, reparent_iter
+from deluge.ui.gtkui.common import (
+ get_clipboard_text,
+ listview_replace_treestore,
+ reparent_iter,
+)
from deluge.ui.gtkui.dialogs import ErrorDialog
from deluge.ui.gtkui.edittrackersdialog import trackers_tiers_from_text
from deluge.ui.gtkui.path_chooser import PathChooser
@@ -38,17 +42,24 @@ class AddTorrentDialog(component.Component):
component.Component.__init__(self, 'AddTorrentDialog')
self.builder = gtk.Builder()
# The base dialog
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'add_torrent_dialog.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'add_torrent_dialog.ui')
+ )
+ )
# The infohash dialog
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'add_torrent_dialog.infohash.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui',
+ os.path.join('glade', 'add_torrent_dialog.infohash.ui'),
+ )
+ )
# The url dialog
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'add_torrent_dialog.url.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'add_torrent_dialog.url.ui')
+ )
+ )
self.dialog = self.builder.get_object('dialog_add_torrent')
@@ -58,7 +69,7 @@ class AddTorrentDialog(component.Component):
# download?, path, filesize, sequence number, inconsistent?
self.files_treestore = gtk.TreeStore(
- bool, str, TYPE_UINT64, TYPE_INT64, bool, str,
+ bool, str, TYPE_UINT64, TYPE_INT64, bool, str
)
self.files_treestore.set_sort_column_id(1, gtk.SORT_ASCENDING)
@@ -110,11 +121,11 @@ class AddTorrentDialog(component.Component):
self.listview_files.set_model(self.files_treestore)
self.listview_files.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
- self.listview_torrents.get_selection().connect('changed', self._on_torrent_changed)
- self.torrent_liststore.connect(
- 'row-inserted', self.update_dialog_title_count)
- self.torrent_liststore.connect(
- 'row-deleted', self.update_dialog_title_count)
+ self.listview_torrents.get_selection().connect(
+ 'changed', self._on_torrent_changed
+ )
+ self.torrent_liststore.connect('row-inserted', self.update_dialog_title_count)
+ self.torrent_liststore.connect('row-deleted', self.update_dialog_title_count)
self.setup_move_completed_path_chooser()
self.setup_download_location_path_chooser()
@@ -136,7 +147,9 @@ class AddTorrentDialog(component.Component):
'move_completed_paths_list',
]
# self.core_keys += self.move_completed_path_chooser.get_config_keys()
- self.builder.get_object('notebook1').connect('switch-page', self._on_switch_page)
+ self.builder.get_object('notebook1').connect(
+ 'switch-page', self._on_switch_page
+ )
def start(self):
self.update_core_config()
@@ -177,9 +190,7 @@ class AddTorrentDialog(component.Component):
d = client.core.get_config_values(self.core_keys)
d.addCallback(self._on_config_values, show, focus)
- def _add_torrent_liststore(
- self, info_hash, name, filename, files, filedata,
- ):
+ def _add_torrent_liststore(self, info_hash, name, filename, files, filedata):
"""Add a torrent to torrent_liststore."""
if info_hash in self.files:
return False
@@ -197,8 +208,7 @@ class AddTorrentDialog(component.Component):
def update_dialog_title_count(self, *args):
"""Update the AddTorrent dialog title with current torrent count."""
- self.dialog.set_title(
- _('Add Torrents (%d)') % len(self.torrent_liststore))
+ self.dialog.set_title(_('Add Torrents (%d)') % len(self.torrent_liststore))
def show_already_added_dialog(self, count):
"""Show a message about trying to add duplicate torrents."""
@@ -207,7 +217,7 @@ class AddTorrentDialog(component.Component):
_('Duplicate torrent(s)'),
_(
'You cannot add the same torrent twice.'
- ' %d torrents were already added.' % count,
+ ' %d torrents were already added.' % count
),
self.dialog,
).run()
@@ -225,11 +235,7 @@ class AddTorrentDialog(component.Component):
continue
if not self._add_torrent_liststore(
- info.info_hash,
- info.name,
- filename,
- info.files,
- info.filedata,
+ info.info_hash, info.name, filename, info.files, info.filedata
):
already_added += 1
@@ -257,12 +263,14 @@ class AddTorrentDialog(component.Component):
"""Show magnet files fetching or failed message above files list."""
if torrent_id in self.prefetching_magnets:
self.builder.get_object('prefetch_label').set_text(
- _('Please wait for files...'))
+ _('Please wait for files...')
+ )
self.builder.get_object('prefetch_spinner').show()
self.builder.get_object('prefetch_hbox').show()
elif not files:
self.builder.get_object('prefetch_label').set_text(
- _('Unable to download files for this magnet'))
+ _('Unable to download files for this magnet')
+ )
self.builder.get_object('prefetch_spinner').hide()
self.builder.get_object('prefetch_hbox').show()
else:
@@ -281,10 +289,7 @@ class AddTorrentDialog(component.Component):
torrent_id = magnet['info_hash']
files = magnet['files_tree']
if not self._add_torrent_liststore(
- torrent_id, magnet['name'],
- xml_escape(uri),
- files,
- None,
+ torrent_id, magnet['name'], xml_escape(uri), files, None
):
already_added += 1
continue
@@ -343,11 +348,7 @@ class AddTorrentDialog(component.Component):
split_files = {}
for idx, _file in enumerate(files):
self.prepare_file(
- _file,
- _file['path'],
- idx,
- _file.get('download', True),
- split_files,
+ _file, _file['path'], idx, _file.get('download', True), split_files
)
self.add_files(None, split_files)
self.listview_files.expand_row(b'0', False)
@@ -357,12 +358,15 @@ class AddTorrentDialog(component.Component):
if first_slash_index == -1:
files_storage[file_name] = (file_num, _file, download)
else:
- file_name_chunk = file_name[:first_slash_index + 1]
+ file_name_chunk = file_name[: first_slash_index + 1]
if file_name_chunk not in files_storage:
files_storage[file_name_chunk] = {}
self.prepare_file(
- _file, file_name[first_slash_index + 1:],
- file_num, download, files_storage[file_name_chunk],
+ _file,
+ file_name[first_slash_index + 1 :],
+ file_num,
+ download,
+ files_storage[file_name_chunk],
)
def add_files(self, parent_iter, split_files):
@@ -370,17 +374,15 @@ class AddTorrentDialog(component.Component):
for key, value in split_files.items():
if key.endswith(os.path.sep):
chunk_iter = self.files_treestore.append(
- parent_iter, [True, key, 0, -1, False, gtk.STOCK_DIRECTORY],
+ parent_iter, [True, key, 0, -1, False, gtk.STOCK_DIRECTORY]
)
chunk_size = self.add_files(chunk_iter, value)
self.files_treestore.set(chunk_iter, 2, chunk_size)
ret += chunk_size
else:
self.files_treestore.append(
- parent_iter, [
- value[2], key, value[1]['size'],
- value[0], False, gtk.STOCK_FILE,
- ],
+ parent_iter,
+ [value[2], key, value[1]['size'], value[0], False, gtk.STOCK_FILE],
)
ret += value[1]['size']
if parent_iter and self.files_treestore.iter_has_child(parent_iter):
@@ -407,24 +409,30 @@ class AddTorrentDialog(component.Component):
def load_path_choosers_data(self):
self.move_completed_path_chooser.set_text(
- self.core_config['move_completed_path'],
- cursor_end=False, default_text=True,
+ self.core_config['move_completed_path'], cursor_end=False, default_text=True
)
self.download_location_path_chooser.set_text(
- self.core_config['download_location'],
- cursor_end=False, default_text=True,
+ self.core_config['download_location'], cursor_end=False, default_text=True
+ )
+ self.builder.get_object('chk_move_completed').set_active(
+ self.core_config['move_completed']
)
- self.builder.get_object('chk_move_completed').set_active(self.core_config['move_completed'])
def setup_move_completed_path_chooser(self):
- self.move_completed_hbox = self.builder.get_object('hbox_move_completed_chooser')
+ self.move_completed_hbox = self.builder.get_object(
+ 'hbox_move_completed_chooser'
+ )
self.move_completed_path_chooser = PathChooser('move_completed_paths_list')
self.move_completed_hbox.add(self.move_completed_path_chooser)
self.move_completed_hbox.show_all()
def setup_download_location_path_chooser(self):
- self.download_location_hbox = self.builder.get_object('hbox_download_location_chooser')
- self.download_location_path_chooser = PathChooser('download_location_paths_list')
+ self.download_location_hbox = self.builder.get_object(
+ 'hbox_download_location_chooser'
+ )
+ self.download_location_path_chooser = PathChooser(
+ 'download_location_paths_list'
+ )
self.download_location_hbox.add(self.download_location_path_chooser)
self.download_location_hbox.show_all()
@@ -435,43 +443,42 @@ class AddTorrentDialog(component.Component):
options = self.options[torrent_id]
- self.download_location_path_chooser.set_text(options['download_location'], cursor_end=True)
- self.move_completed_path_chooser.set_text(options['move_completed_path'], cursor_end=True)
-
- self.builder.get_object('spin_maxdown').set_value(
- options['max_download_speed'],
+ self.download_location_path_chooser.set_text(
+ options['download_location'], cursor_end=True
)
- self.builder.get_object('spin_maxup').set_value(
- options['max_upload_speed'],
+ self.move_completed_path_chooser.set_text(
+ options['move_completed_path'], cursor_end=True
)
+
+ self.builder.get_object('spin_maxdown').set_value(options['max_download_speed'])
+ self.builder.get_object('spin_maxup').set_value(options['max_upload_speed'])
self.builder.get_object('spin_maxconnections').set_value(
- options['max_connections'],
+ options['max_connections']
)
self.builder.get_object('spin_maxupslots').set_value(
- options['max_upload_slots'],
- )
- self.builder.get_object('chk_paused').set_active(
- options['add_paused'],
+ options['max_upload_slots']
)
+ self.builder.get_object('chk_paused').set_active(options['add_paused'])
self.builder.get_object('chk_pre_alloc').set_active(
- options['pre_allocate_storage'],
+ options['pre_allocate_storage']
)
self.builder.get_object('chk_prioritize').set_active(
- options['prioritize_first_last_pieces'],
+ options['prioritize_first_last_pieces']
)
self.builder.get_object('chk_sequential_download').set_active(
- options['sequential_download'],
+ options['sequential_download']
)
self.builder.get_object('chk_move_completed').set_active(
- options['move_completed'],
+ options['move_completed']
)
def save_torrent_options(self, row=None):
# Keeps the torrent options dictionary up-to-date with what the user has
# selected.
if row is None:
- if self.previous_selected_torrent and \
- self.torrent_liststore.iter_is_valid(self.previous_selected_torrent):
+ if self.previous_selected_torrent and self.torrent_liststore.iter_is_valid(
+ self.previous_selected_torrent
+ ):
row = self.previous_selected_torrent
else:
return
@@ -485,25 +492,39 @@ class AddTorrentDialog(component.Component):
options['download_location'] = self.download_location_path_chooser.get_text()
options['move_completed_path'] = self.move_completed_path_chooser.get_text()
- options['pre_allocate_storage'] = self.builder.get_object('chk_pre_alloc').get_active()
- options['move_completed'] = self.builder.get_object('chk_move_completed').get_active()
- options['max_download_speed'] = self.builder.get_object('spin_maxdown').get_value()
+ options['pre_allocate_storage'] = self.builder.get_object(
+ 'chk_pre_alloc'
+ ).get_active()
+ options['move_completed'] = self.builder.get_object(
+ 'chk_move_completed'
+ ).get_active()
+ options['max_download_speed'] = self.builder.get_object(
+ 'spin_maxdown'
+ ).get_value()
options['max_upload_speed'] = self.builder.get_object('spin_maxup').get_value()
- options['max_connections'] = self.builder.get_object('spin_maxconnections').get_value_as_int()
- options['max_upload_slots'] = self.builder.get_object('spin_maxupslots').get_value_as_int()
+ options['max_connections'] = self.builder.get_object(
+ 'spin_maxconnections'
+ ).get_value_as_int()
+ options['max_upload_slots'] = self.builder.get_object(
+ 'spin_maxupslots'
+ ).get_value_as_int()
options['add_paused'] = self.builder.get_object('chk_paused').get_active()
- options['prioritize_first_last_pieces'] = self.builder.get_object('chk_prioritize').get_active()
- options['sequential_download'] = self.builder.get_object(
- 'chk_sequential_download',
- ).get_active() or False
- options['move_completed'] = self.builder.get_object('chk_move_completed').get_active()
+ options['prioritize_first_last_pieces'] = self.builder.get_object(
+ 'chk_prioritize'
+ ).get_active()
+ options['sequential_download'] = (
+ self.builder.get_object('chk_sequential_download').get_active() or False
+ )
+ options['move_completed'] = self.builder.get_object(
+ 'chk_move_completed'
+ ).get_active()
options['seed_mode'] = self.builder.get_object('chk_seed_mode').get_active()
self.options[torrent_id] = options
# Save the file priorities
files_priorities = self.build_priorities(
- self.files_treestore.get_iter_first(), {},
+ self.files_treestore.get_iter_first(), {}
)
if len(files_priorities) > 0:
@@ -513,9 +534,13 @@ class AddTorrentDialog(component.Component):
def build_priorities(self, _iter, priorities):
while _iter is not None:
if self.files_treestore.iter_has_child(_iter):
- self.build_priorities(self.files_treestore.iter_children(_iter), priorities)
+ self.build_priorities(
+ self.files_treestore.iter_children(_iter), priorities
+ )
elif not self.files_treestore.get_value(_iter, 1).endswith(os.path.sep):
- priorities[self.files_treestore.get_value(_iter, 3)] = self.files_treestore.get_value(_iter, 0)
+ priorities[
+ self.files_treestore.get_value(_iter, 3)
+ ] = self.files_treestore.get_value(_iter, 0)
_iter = self.files_treestore.iter_next(_iter)
return priorities
@@ -528,31 +553,29 @@ class AddTorrentDialog(component.Component):
self.load_path_choosers_data()
self.builder.get_object('chk_pre_alloc').set_active(
- self.core_config['pre_allocate_storage'],
+ self.core_config['pre_allocate_storage']
)
self.builder.get_object('spin_maxdown').set_value(
- self.core_config['max_download_speed_per_torrent'],
+ self.core_config['max_download_speed_per_torrent']
)
self.builder.get_object('spin_maxup').set_value(
- self.core_config['max_upload_speed_per_torrent'],
+ self.core_config['max_upload_speed_per_torrent']
)
self.builder.get_object('spin_maxconnections').set_value(
- self.core_config['max_connections_per_torrent'],
+ self.core_config['max_connections_per_torrent']
)
self.builder.get_object('spin_maxupslots').set_value(
- self.core_config['max_upload_slots_per_torrent'],
- )
- self.builder.get_object('chk_paused').set_active(
- self.core_config['add_paused'],
+ self.core_config['max_upload_slots_per_torrent']
)
+ self.builder.get_object('chk_paused').set_active(self.core_config['add_paused'])
self.builder.get_object('chk_prioritize').set_active(
- self.core_config['prioritize_first_last_pieces'],
+ self.core_config['prioritize_first_last_pieces']
)
self.builder.get_object('chk_sequential_download').set_active(
- self.core_config['sequential_download'],
+ self.core_config['sequential_download']
)
self.builder.get_object('chk_move_completed').set_active(
- self.core_config['move_completed'],
+ self.core_config['move_completed']
)
self.builder.get_object('chk_seed_mode').set_active(False)
@@ -595,7 +618,9 @@ class AddTorrentDialog(component.Component):
this_level_toggle = None
while _iter is not None:
if self.files_treestore.iter_has_child(_iter):
- toggle = self.update_treeview_toggles(self.files_treestore.iter_children(_iter))
+ toggle = self.update_treeview_toggles(
+ self.files_treestore.iter_children(_iter)
+ )
if toggle == toggle_inconsistent:
self.files_treestore.set_value(_iter, 4, True)
else:
@@ -619,7 +644,9 @@ class AddTorrentDialog(component.Component):
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN,
gtk.RESPONSE_OK,
),
)
@@ -699,7 +726,9 @@ class AddTorrentDialog(component.Component):
def add_from_url(self, url):
dialog = gtk.Dialog(
_('Downloading...'),
- flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR,
+ flags=gtk.DIALOG_MODAL
+ | gtk.DIALOG_DESTROY_WITH_PARENT
+ | gtk.DIALOG_NO_SEPARATOR,
parent=self.dialog,
)
dialog.set_transient_for(self.dialog)
@@ -710,17 +739,21 @@ class AddTorrentDialog(component.Component):
# Create a tmp file path
import tempfile
+
tmp_fd, tmp_file = tempfile.mkstemp(prefix='deluge_url.', suffix='.torrent')
def on_part(data, current_length, total_length):
if total_length:
percent = current_length / total_length
pb.set_fraction(percent)
- pb.set_text('%.2f%% (%s / %s)' % (
- percent * 100,
- deluge.common.fsize(current_length),
- deluge.common.fsize(total_length),
- ))
+ pb.set_text(
+ '%.2f%% (%s / %s)'
+ % (
+ percent * 100,
+ deluge.common.fsize(current_length),
+ deluge.common.fsize(total_length),
+ )
+ )
else:
pb.pulse()
pb.set_text('%s' % deluge.common.fsize(current_length))
@@ -733,8 +766,10 @@ class AddTorrentDialog(component.Component):
log.debug('Download failed: %s', result)
dialog.destroy()
ErrorDialog(
- _('Download Failed'), '%s %s' % (_('Failed to download:'), url),
- details=result.getErrorMessage(), parent=self.dialog,
+ _('Download Failed'),
+ '%s %s' % (_('Failed to download:'), url),
+ details=result.getErrorMessage(),
+ parent=self.dialog,
).run()
return result
@@ -822,11 +857,13 @@ class AddTorrentDialog(component.Component):
options['file_priorities'] = file_priorities
if self.infos[torrent_id]:
- torrents_to_add.append((
- os.path.split(filename)[-1],
- b64encode(self.infos[torrent_id]),
- options,
- ))
+ torrents_to_add.append(
+ (
+ os.path.split(filename)[-1],
+ b64encode(self.infos[torrent_id]),
+ options,
+ )
+ )
elif deluge.common.is_magnet(filename):
client.core.add_torrent_magnet(filename, options)
@@ -834,11 +871,16 @@ class AddTorrentDialog(component.Component):
def on_torrents_added(errors):
if errors:
- log.info('Failed to add %d out of %d torrents.', len(errors), len(torrents_to_add))
+ log.info(
+ 'Failed to add %d out of %d torrents.',
+ len(errors),
+ len(torrents_to_add),
+ )
for e in errors:
log.info('Torrent add failed: %s', e)
else:
log.info('Successfully added %d torrents.', len(torrents_to_add))
+
client.core.add_torrent_files(torrents_to_add).addCallback(on_torrents_added)
def on_button_apply_clicked(self, widget):
@@ -919,7 +961,9 @@ class AddTorrentDialog(component.Component):
# and then move the file iter to top
split_text = new_text.split(os.path.sep)
for s in split_text[:-1]:
- parent = self.files_treestore.append(parent, [True, s, 0, -1, False, gtk.STOCK_DIRECTORY])
+ parent = self.files_treestore.append(
+ parent, [True, s, 0, -1, False, gtk.STOCK_DIRECTORY]
+ )
self.files_treestore[itr][1] = split_text[-1]
reparent_iter(self.files_treestore, itr, parent)
@@ -942,7 +986,7 @@ class AddTorrentDialog(component.Component):
# Get the file path base once, since it will be the same for
# all siblings
file_path_base = self.get_file_path(
- self.files_treestore.iter_parent(row),
+ self.files_treestore.iter_parent(row)
)
# Iterate through all the siblings at this level
@@ -977,9 +1021,8 @@ class AddTorrentDialog(component.Component):
# We don't iterate over the last item because we'll just use
# the existing itr and change the text
parent = self.files_treestore.append(
- parent, [
- True, s + os.path.sep, 0, -1, False, gtk.STOCK_DIRECTORY,
- ],
+ parent,
+ [True, s + os.path.sep, 0, -1, False, gtk.STOCK_DIRECTORY],
)
self.files_treestore[itr][1] = split_text[-1] + os.path.sep
diff --git a/deluge/ui/gtkui/common.py b/deluge/ui/gtkui/common.py
index a8701b49a..a02eace0a 100644
--- a/deluge/ui/gtkui/common.py
+++ b/deluge/ui/gtkui/common.py
@@ -17,8 +17,22 @@ import sys
import six.moves.cPickle as pickle
from gobject import GError
-from gtk import SORT_ASCENDING, Menu, MenuItem, RadioMenuItem, SeparatorMenuItem, clipboard_get, icon_theme_get_default
-from gtk.gdk import COLORSPACE_RGB, SELECTION_PRIMARY, Pixbuf, pixbuf_new_from_file, pixbuf_new_from_file_at_size
+from gtk import (
+ SORT_ASCENDING,
+ Menu,
+ MenuItem,
+ RadioMenuItem,
+ SeparatorMenuItem,
+ clipboard_get,
+ icon_theme_get_default,
+)
+from gtk.gdk import (
+ COLORSPACE_RGB,
+ SELECTION_PRIMARY,
+ Pixbuf,
+ pixbuf_new_from_file,
+ pixbuf_new_from_file_at_size,
+)
from deluge.common import get_pixmap, osx_check, windows_check
@@ -73,8 +87,14 @@ def get_logo(size):
def build_menu_radio_list(
- value_list, callback, pref_value=None, suffix=None, show_notset=False,
- notset_label='∞', notset_lessthan=0, show_other=False,
+ value_list,
+ callback,
+ pref_value=None,
+ suffix=None,
+ show_notset=False,
+ notset_label='∞',
+ notset_lessthan=0,
+ show_other=False,
):
"""Build a menu with radio menu items from a list and connect them to the callback.
@@ -145,7 +165,9 @@ def reparent_iter(treestore, itr, parent, move_siblings=False):
def move_children(i, dest):
while i:
- n_cols = treestore.append(dest, treestore.get(i, *range(treestore.get_n_columns())))
+ n_cols = treestore.append(
+ dest, treestore.get(i, *range(treestore.get_n_columns()))
+ )
to_remove = i
if treestore.iter_children(i):
move_children(treestore.iter_children(i), n_cols)
@@ -208,13 +230,22 @@ def associate_magnet_links(overwrite=False):
magnet_key = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, 'Magnet')
except WindowsError:
# Could not create for all users, falling back to current user
- magnet_key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet')
+ magnet_key = winreg.CreateKey(
+ winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet'
+ )
winreg.SetValue(magnet_key, '', winreg.REG_SZ, 'URL:Magnet Protocol')
winreg.SetValueEx(magnet_key, 'URL Protocol', 0, winreg.REG_SZ, '')
winreg.SetValueEx(magnet_key, 'BrowserFlags', 0, winreg.REG_DWORD, 0x8)
- winreg.SetValue(magnet_key, 'DefaultIcon', winreg.REG_SZ, '{},0'.format(deluge_exe))
- winreg.SetValue(magnet_key, r'shell\open\command', winreg.REG_SZ, '"{}" "%1"'.format(deluge_exe))
+ winreg.SetValue(
+ magnet_key, 'DefaultIcon', winreg.REG_SZ, '{},0'.format(deluge_exe)
+ )
+ winreg.SetValue(
+ magnet_key,
+ r'shell\open\command',
+ winreg.REG_SZ,
+ '"{}" "%1"'.format(deluge_exe),
+ )
winreg.CloseKey(magnet_key)
# Don't try associate magnet on OSX see: #2420
@@ -223,7 +254,9 @@ def associate_magnet_links(overwrite=False):
try:
import gconf
except ImportError:
- log.debug('gconf not available, so will not attempt to register magnet uri handler')
+ log.debug(
+ 'gconf not available, so will not attempt to register magnet uri handler'
+ )
return False
else:
key = '/desktop/gnome/url-handlers/magnet/command'
@@ -231,12 +264,18 @@ def associate_magnet_links(overwrite=False):
if (gconf_client.get(key) and overwrite) or not gconf_client.get(key):
# We are either going to overwrite the key, or do it if it hasn't been set yet
if gconf_client.set_string(key, 'deluge "%s"'):
- gconf_client.set_bool('/desktop/gnome/url-handlers/magnet/needs_terminal', False)
- gconf_client.set_bool('/desktop/gnome/url-handlers/magnet/enabled', True)
+ gconf_client.set_bool(
+ '/desktop/gnome/url-handlers/magnet/needs_terminal', False
+ )
+ gconf_client.set_bool(
+ '/desktop/gnome/url-handlers/magnet/enabled', True
+ )
log.info('Deluge registered as default magnet uri handler!')
return True
else:
- log.error('Unable to register Deluge as default magnet uri handler.')
+ log.error(
+ 'Unable to register Deluge as default magnet uri handler.'
+ )
return False
return False
@@ -249,6 +288,7 @@ def save_pickled_state_file(filename, state):
state (state): The data to be pickled and written to file
"""
from deluge.configmanager import get_config_dir
+
filepath = os.path.join(get_config_dir(), 'gtkui_state', filename)
filepath_bak = filepath + '.bak'
filepath_tmp = filepath + '.tmp'
@@ -285,6 +325,7 @@ def load_pickled_state_file(filename):
state: the unpickled state
"""
from deluge.configmanager import get_config_dir
+
filepath = os.path.join(get_config_dir(), 'gtkui_state', filename)
filepath_bak = filepath + '.bak'
old_data_filepath = os.path.join(get_config_dir(), filename)
@@ -328,6 +369,9 @@ def listview_replace_treestore(listview):
def get_clipboard_text():
- text = clipboard_get(selection=SELECTION_PRIMARY).wait_for_text() or clipboard_get().wait_for_text()
+ text = (
+ clipboard_get(selection=SELECTION_PRIMARY).wait_for_text()
+ or clipboard_get().wait_for_text()
+ )
if text:
return text.strip()
diff --git a/deluge/ui/gtkui/connectionmanager.py b/deluge/ui/gtkui/connectionmanager.py
index 5b860e699..6320f649a 100644
--- a/deluge/ui/gtkui/connectionmanager.py
+++ b/deluge/ui/gtkui/connectionmanager.py
@@ -45,11 +45,7 @@ HOSTLIST_PIXBUFS = [
# This is populated in ConnectionManager.show
]
-HOSTLIST_STATUS = [
- 'Offline',
- 'Online',
- 'Connected',
-]
+HOSTLIST_STATUS = ['Offline', 'Online', 'Connected']
def cell_render_host(column, cell, model, row, data):
@@ -92,9 +88,11 @@ class ConnectionManager(component.Component):
def show(self):
"""Show the ConnectionManager dialog."""
self.builder = gtk.Builder()
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.ui')
+ )
+ )
self.connection_manager = self.builder.get_object('connection_manager')
self.connection_manager.set_transient_for(component.get('MainWindow').window)
@@ -102,7 +100,7 @@ class ConnectionManager(component.Component):
if not HOSTLIST_PIXBUFS:
for stock_id in (gtk.STOCK_NO, gtk.STOCK_YES, gtk.STOCK_CONNECT):
HOSTLIST_PIXBUFS.append(
- self.connection_manager.render_icon(stock_id, gtk.ICON_SIZE_MENU),
+ self.connection_manager.render_icon(stock_id, gtk.ICON_SIZE_MENU)
)
# Setup the hostlist liststore and treeview
@@ -121,7 +119,9 @@ class ConnectionManager(component.Component):
column.set_expand(True)
self.treeview.append_column(column)
- column = gtk.TreeViewColumn(_('Version'), gtk.CellRendererText(), text=HOSTLIST_COL_VERSION)
+ column = gtk.TreeViewColumn(
+ _('Version'), gtk.CellRendererText(), text=HOSTLIST_COL_VERSION
+ )
self.treeview.append_column(column)
# Load any saved host entries
@@ -132,7 +132,9 @@ class ConnectionManager(component.Component):
# Connect the signals to the handlers
self.builder.connect_signals(self)
- self.treeview.get_selection().connect('changed', self.on_hostlist_selection_changed)
+ self.treeview.get_selection().connect(
+ 'changed', self.on_hostlist_selection_changed
+ )
# Set running True before update status call.
self.running = True
@@ -167,13 +169,13 @@ class ConnectionManager(component.Component):
def _load_widget_config(self):
"""Set the widgets to show the correct options from the config."""
self.builder.get_object('chk_autoconnect').set_active(
- self.gtkui_config['autoconnect'],
+ self.gtkui_config['autoconnect']
)
self.builder.get_object('chk_autostart').set_active(
- self.gtkui_config['autostart_localhost'],
+ self.gtkui_config['autostart_localhost']
)
self.builder.get_object('chk_donotshow').set_active(
- not self.gtkui_config['show_connection_manager_on_start'],
+ not self.gtkui_config['show_connection_manager_on_start']
)
def _update_host_status(self):
@@ -210,9 +212,11 @@ class ConnectionManager(component.Component):
self.builder.get_object('button_removehost').set_sensitive(False)
self.builder.get_object('button_startdaemon').set_sensitive(False)
self.builder.get_object('image_startdaemon').set_from_stock(
- gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU,
+ gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU
+ )
+ self.builder.get_object('label_startdaemon').set_text_with_mnemonic(
+ '_Start Daemon'
)
- self.builder.get_object('label_startdaemon').set_text_with_mnemonic('_Start Daemon')
model, row = self.treeview.get_selection().get_selected()
if row:
@@ -226,7 +230,9 @@ class ConnectionManager(component.Component):
try:
gethostbyname(host)
except gaierror as ex:
- log.error('Error resolving host %s to ip: %s', row[HOSTLIST_COL_HOST], ex.args[1])
+ log.error(
+ 'Error resolving host %s to ip: %s', row[HOSTLIST_COL_HOST], ex.args[1]
+ )
self.builder.get_object('button_connect').set_sensitive(False)
return
@@ -236,9 +242,11 @@ class ConnectionManager(component.Component):
if status == 'Connected' or status == 'Online':
self.builder.get_object('button_connect').set_sensitive(True)
self.builder.get_object('image_startdaemon').set_from_stock(
- gtk.STOCK_STOP, gtk.ICON_SIZE_MENU,
+ gtk.STOCK_STOP, gtk.ICON_SIZE_MENU
+ )
+ self.builder.get_object('label_startdaemon').set_text_with_mnemonic(
+ _('_Stop Daemon')
)
- self.builder.get_object('label_startdaemon').set_text_with_mnemonic(_('_Stop Daemon'))
self.builder.get_object('button_startdaemon').set_sensitive(False)
if status == 'Connected':
# Display a disconnect button if we're connected to this host
@@ -315,6 +323,7 @@ class ConnectionManager(component.Component):
def dialog_finished(response_id):
if response_id == gtk.RESPONSE_OK:
self._connect(host_id, dialog.get_username(), dialog.get_password())
+
return dialog.run().addCallback(dialog_finished)
elif reason.check(IncompatibleClient):
@@ -322,13 +331,15 @@ class ConnectionManager(component.Component):
if try_counter:
log.info('Retrying connection.. Retries left: %s', try_counter)
- return reactor.callLater(0.5, self._connect, host_id, try_counter=try_counter - 1)
+ return reactor.callLater(
+ 0.5, self._connect, host_id, try_counter=try_counter - 1
+ )
msg = str(reason.value)
if not self.gtkui_config['autostart_localhost']:
msg += '\n' + _(
'Auto-starting the daemon locally is not enabled. '
- 'See "Options" on the "Connection Manager".',
+ 'See "Options" on the "Connection Manager".'
)
ErrorDialog(_('Failed To Connect'), msg).run()
@@ -341,8 +352,10 @@ class ConnectionManager(component.Component):
host_id, host, port, __, __, status, __ = model[row]
# If status is connected then connect button disconnects instead.
if status == 'Connected':
+
def on_disconnect(reason):
self._update_host_status()
+
return client.disconnect().addCallback(on_disconnect)
try_counter = 0
@@ -372,9 +385,12 @@ class ConnectionManager(component.Component):
list: The new host info values (host, port, user, pass).
"""
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.addhost.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui',
+ os.path.join('glade', 'connection_manager.addhost.ui'),
+ )
+ )
dialog = self.builder.get_object('addhost_dialog')
dialog.set_transient_for(self.connection_manager)
hostname_entry = self.builder.get_object('entry_hostname')
@@ -410,7 +426,9 @@ class ConnectionManager(component.Component):
except ValueError as ex:
ErrorDialog(_('Error Adding Host'), ex).run()
else:
- self.liststore.append([host_id, hostname, port, username, password, 'Offline', ''])
+ self.liststore.append(
+ [host_id, hostname, port, username, password, 'Offline', '']
+ )
self._update_host_status()
def on_button_edithost_clicked(self, widget=None):
@@ -420,8 +438,10 @@ class ConnectionManager(component.Component):
host_id = model[row][HOSTLIST_COL_ID]
if status == 'Connected':
+
def on_disconnect(reason):
self._update_host_status()
+
client.disconnect().addCallback(on_disconnect)
return
@@ -439,7 +459,15 @@ class ConnectionManager(component.Component):
except ValueError as ex:
ErrorDialog(_('Error Updating Host'), ex).run()
else:
- self.liststore[row] = host_id, hostname, port, username, password, '', ''
+ self.liststore[row] = (
+ host_id,
+ hostname,
+ port,
+ username,
+ password,
+ '',
+ '',
+ )
self._update_host_status()
def on_button_removehost_clicked(self, widget):
@@ -502,11 +530,15 @@ class ConnectionManager(component.Component):
self._update_widget_buttons()
def on_chk_toggled(self, widget):
- self.gtkui_config['autoconnect'] = self.builder.get_object('chk_autoconnect').get_active()
- self.gtkui_config['autostart_localhost'] = self.builder.get_object('chk_autostart').get_active()
- self.gtkui_config['show_connection_manager_on_start'] = not self.builder.get_object(
- 'chk_donotshow',
+ self.gtkui_config['autoconnect'] = self.builder.get_object(
+ 'chk_autoconnect'
+ ).get_active()
+ self.gtkui_config['autostart_localhost'] = self.builder.get_object(
+ 'chk_autostart'
).get_active()
+ self.gtkui_config[
+ 'show_connection_manager_on_start'
+ ] = not self.builder.get_object('chk_donotshow').get_active()
def on_entry_host_paste_clipboard(self, widget):
text = get_clipboard_text()
diff --git a/deluge/ui/gtkui/createtorrentdialog.py b/deluge/ui/gtkui/createtorrentdialog.py
index 5ca7586fc..8a61ee3d1 100644
--- a/deluge/ui/gtkui/createtorrentdialog.py
+++ b/deluge/ui/gtkui/createtorrentdialog.py
@@ -21,14 +21,16 @@ import deluge.component as component
from deluge.common import get_path_size, is_url, resource_filename
from deluge.configmanager import ConfigManager
from deluge.ui.client import client
-from deluge.ui.gtkui.edittrackersdialog import last_tier_trackers_from_liststore, trackers_tiers_from_text
+from deluge.ui.gtkui.edittrackersdialog import (
+ last_tier_trackers_from_liststore,
+ trackers_tiers_from_text,
+)
from deluge.ui.gtkui.torrentview_data_funcs import cell_data_size
log = logging.getLogger(__name__)
class CreateTorrentDialog(object):
-
def __init__(self):
pass
@@ -36,21 +38,32 @@ class CreateTorrentDialog(object):
self.builder = gtk.Builder()
# The main dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'create_torrent_dialog.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'create_torrent_dialog.ui')
+ )
+ )
# The remote path dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'create_torrent_dialog.remote_path.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui',
+ os.path.join('glade', 'create_torrent_dialog.remote_path.ui'),
+ )
+ )
# The remote save dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'create_torrent_dialog.remote_save.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui',
+ os.path.join('glade', 'create_torrent_dialog.remote_save.ui'),
+ )
+ )
# The progress dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'create_torrent_dialog.progress.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui',
+ os.path.join('glade', 'create_torrent_dialog.progress.ui'),
+ )
+ )
self.config = ConfigManager('gtkui.conf')
@@ -85,10 +98,10 @@ class CreateTorrentDialog(object):
self.trackers_liststore = gtk.ListStore(int, str)
self.builder.get_object('tracker_treeview').append_column(
- gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0),
+ gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0)
)
self.builder.get_object('tracker_treeview').append_column(
- gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1),
+ gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1)
)
self.builder.get_object('tracker_treeview').set_model(self.trackers_liststore)
@@ -132,8 +145,10 @@ class CreateTorrentDialog(object):
self.dialog,
gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN,
+ gtk.RESPONSE_OK,
),
)
@@ -165,8 +180,10 @@ class CreateTorrentDialog(object):
self.dialog,
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
buttons=(
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN,
+ gtk.RESPONSE_OK,
),
)
@@ -207,6 +224,7 @@ class CreateTorrentDialog(object):
self.files_treestore.clear()
self.files_treestore.append(None, [result, gtk.STOCK_NETWORK, size])
self.adjust_piece_size()
+
client.core.get_path_size(result).addCallback(_on_get_path_size)
client.force_call(True)
@@ -243,11 +261,14 @@ class CreateTorrentDialog(object):
else:
# Setup the filechooserdialog
chooser = gtk.FileChooserDialog(
- _('Save .torrent file'), self.dialog,
+ _('Save .torrent file'),
+ self.dialog,
gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_SAVE, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,
+ gtk.STOCK_SAVE,
+ gtk.RESPONSE_OK,
),
)
@@ -306,7 +327,9 @@ class CreateTorrentDialog(object):
webseeds.append(line)
# Get the piece length in bytes
combo = self.builder.get_object('combo_piece_size')
- piece_length = self.parse_piece_size_text(combo.get_model()[combo.get_active()][0])
+ piece_length = self.parse_piece_size_text(
+ combo.get_model()[combo.get_active()][0]
+ )
author = self.builder.get_object('entry_author').get_text()
comment = self.builder.get_object('entry_comments').get_text()
@@ -314,17 +337,23 @@ class CreateTorrentDialog(object):
add_to_session = self.builder.get_object('chk_add_to_session').get_active()
if is_remote:
+
def torrent_created():
self.builder.get_object('progress_dialog').hide_all()
- client.deregister_event_handler('CreateTorrentProgressEvent', on_create_torrent_progress_event)
+ client.deregister_event_handler(
+ 'CreateTorrentProgressEvent', on_create_torrent_progress_event
+ )
def on_create_torrent_progress_event(piece_count, num_pieces):
self._on_create_torrent_progress(piece_count, num_pieces)
if piece_count == num_pieces:
from twisted.internet import reactor
+
reactor.callLater(0.5, torrent_created)
- client.register_event_handler('CreateTorrentProgressEvent', on_create_torrent_progress_event)
+ client.register_event_handler(
+ 'CreateTorrentProgressEvent', on_create_torrent_progress_event
+ )
client.core.create_torrent(
path,
@@ -360,16 +389,29 @@ class CreateTorrentDialog(object):
).addCallback(hide_progress)
# Setup progress dialog
- self.builder.get_object('progress_dialog').set_transient_for(component.get('MainWindow').window)
+ self.builder.get_object('progress_dialog').set_transient_for(
+ component.get('MainWindow').window
+ )
self.builder.get_object('progress_dialog').show_all()
self.dialog.destroy()
def create_torrent(
- self, path, tracker, piece_length, progress, comment, target,
- webseeds, private, created_by, trackers, add_to_session,
+ self,
+ path,
+ tracker,
+ piece_length,
+ progress,
+ comment,
+ target,
+ webseeds,
+ private,
+ created_by,
+ trackers,
+ add_to_session,
):
import deluge.metafile
+
deluge.metafile.make_meta_file(
path,
tracker,
@@ -408,7 +450,11 @@ class CreateTorrentDialog(object):
def on_button_up_clicked(self, widget):
log.debug('on_button_up_clicked')
- row = self.builder.get_object('tracker_treeview').get_selection().get_selected()[1]
+ row = (
+ self.builder.get_object('tracker_treeview')
+ .get_selection()
+ .get_selected()[1]
+ )
if row is None:
return
if self.trackers_liststore[row][0] == 0:
@@ -418,7 +464,11 @@ class CreateTorrentDialog(object):
def on_button_down_clicked(self, widget):
log.debug('on_button_down_clicked')
- row = self.builder.get_object('tracker_treeview').get_selection().get_selected()[1]
+ row = (
+ self.builder.get_object('tracker_treeview')
+ .get_selection()
+ .get_selected()[1]
+ )
if row is None:
return
self.trackers_liststore[row][0] += 1
@@ -426,14 +476,18 @@ class CreateTorrentDialog(object):
def on_button_add_clicked(self, widget):
log.debug('on_button_add_clicked')
builder = gtk.Builder()
- builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.add.ui'),
- ))
+ builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.add.ui')
+ )
+ )
dialog = builder.get_object('add_tracker_dialog')
dialog.set_transient_for(self.dialog)
textview = builder.get_object('textview_trackers')
if self.config['createtorrent.trackers']:
- textview.get_buffer().set_text('\n'.join(self.config['createtorrent.trackers']))
+ textview.get_buffer().set_text(
+ '\n'.join(self.config['createtorrent.trackers'])
+ )
else:
textview.get_buffer().set_text('')
textview.grab_focus()
@@ -447,7 +501,9 @@ class CreateTorrentDialog(object):
self.config['createtorrent.trackers'] = trackers_text.split('/n')
# Append trackers liststore with unique trackers and tiers starting from last tier number.
- last_tier, orig_trackers = last_tier_trackers_from_liststore(self.trackers_liststore)
+ last_tier, orig_trackers = last_tier_trackers_from_liststore(
+ self.trackers_liststore
+ )
for tracker, tier in trackers_tiers_from_text(trackers_text).items():
if tracker not in orig_trackers:
self.trackers_liststore.append([tier + last_tier, tracker])
@@ -456,7 +512,11 @@ class CreateTorrentDialog(object):
def on_button_remove_clicked(self, widget):
log.debug('on_button_remove_clicked')
- row = self.builder.get_object('tracker_treeview').get_selection().get_selected()[1]
+ row = (
+ self.builder.get_object('tracker_treeview')
+ .get_selection()
+ .get_selected()[1]
+ )
if row is None:
return
self.trackers_liststore.remove(row)
diff --git a/deluge/ui/gtkui/details_tab.py b/deluge/ui/gtkui/details_tab.py
index b6e921e04..06f9e944d 100644
--- a/deluge/ui/gtkui/details_tab.py
+++ b/deluge/ui/gtkui/details_tab.py
@@ -33,7 +33,9 @@ class DetailsTab(Tab):
self.add_tab_widget('summary_hash', str, ('hash',))
self.add_tab_widget('summary_comments', str, ('comment',))
self.add_tab_widget('summary_creator', str, ('creator',))
- self.add_tab_widget('summary_pieces', fpieces_num_size, ('num_pieces', 'piece_length'))
+ self.add_tab_widget(
+ 'summary_pieces', fpieces_num_size, ('num_pieces', 'piece_length')
+ )
def update(self):
# Get the first selected torrent
@@ -48,7 +50,9 @@ class DetailsTab(Tab):
return
session = component.get('SessionProxy')
- session.get_torrent_status(selected, self.status_keys).addCallback(self._on_get_torrent_status)
+ session.get_torrent_status(selected, self.status_keys).addCallback(
+ self._on_get_torrent_status
+ )
def _on_get_torrent_status(self, status):
# Check to see if we got valid data from the core
diff --git a/deluge/ui/gtkui/dialogs.py b/deluge/ui/gtkui/dialogs.py
index 91b299bb3..562b2ce51 100644
--- a/deluge/ui/gtkui/dialogs.py
+++ b/deluge/ui/gtkui/dialogs.py
@@ -23,6 +23,7 @@ class BaseDialog(gtk.Dialog):
"""
Base dialog class that should be used with all dialogs.
"""
+
def __init__(self, header, text, icon, buttons, parent=None):
"""
:param header: str, the header portion of the dialog
@@ -35,7 +36,9 @@ class BaseDialog(gtk.Dialog):
super(BaseDialog, self).__init__(
title=header,
parent=parent if parent else component.get('MainWindow').window,
- flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR,
+ flags=gtk.DIALOG_MODAL
+ | gtk.DIALOG_DESTROY_WITH_PARENT
+ | gtk.DIALOG_NO_SEPARATOR,
buttons=buttons,
)
@@ -49,7 +52,9 @@ class BaseDialog(gtk.Dialog):
self.set_default_size(200, 100)
hbox = gtk.HBox(spacing=5)
image = gtk.Image()
- if not gtk.stock_lookup(icon) and (icon.endswith('.svg') or icon.endswith('.png')):
+ if not gtk.stock_lookup(icon) and (
+ icon.endswith('.svg') or icon.endswith('.png')
+ ):
# Hack for Windows since it doesn't support svg
if icon.endswith('.svg') and windows_check():
icon = icon.rpartition('.svg')[0] + '16.png'
@@ -94,6 +99,7 @@ class YesNoDialog(BaseDialog):
When run(), it will return either a gtk.RESPONSE_YES or a gtk.RESPONSE_NO.
"""
+
def __init__(self, header, text, parent=None):
"""
:param header: see `:class:BaseDialog`
@@ -115,6 +121,7 @@ class InformationDialog(BaseDialog):
When run(), it will return a gtk.RESPONSE_CLOSE.
"""
+
def __init__(self, header, text, parent=None):
"""
:param header: see `:class:BaseDialog`
@@ -136,6 +143,7 @@ class ErrorDialog(BaseDialog):
When run(), it will return a gtk.RESPONSE_CLOSE.
"""
+
def __init__(self, header, text, parent=None, details=None, traceback=False):
"""
:param header: see `:class:BaseDialog`
@@ -158,6 +166,7 @@ class ErrorDialog(BaseDialog):
if traceback:
import traceback
import sys
+
tb = sys.exc_info()
tb = traceback.format_exc(tb[2])
if details:
@@ -188,13 +197,15 @@ class AuthenticationDialog(BaseDialog):
When run(), it will return either a gtk.RESPONSE_CANCEL or a
gtk.RESPONSE_OK.
"""
+
def __init__(self, err_msg='', username=None, parent=None):
"""
:param err_msg: the error message we got back from the server
:type err_msg: string
"""
super(AuthenticationDialog, self).__init__(
- _('Authenticate'), err_msg,
+ _('Authenticate'),
+ err_msg,
gtk.STOCK_DIALOG_AUTHENTICATION,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_CONNECT, gtk.RESPONSE_OK),
parent,
@@ -241,8 +252,12 @@ class AuthenticationDialog(BaseDialog):
class AccountDialog(BaseDialog):
def __init__(
- self, username=None, password=None, authlevel=None,
- levels_mapping=None, parent=None,
+ self,
+ username=None,
+ password=None,
+ authlevel=None,
+ levels_mapping=None,
+ parent=None,
):
if username:
super(AccountDialog, self).__init__(
@@ -250,8 +265,10 @@ class AccountDialog(BaseDialog):
_('Edit existing account'),
gtk.STOCK_DIALOG_INFO,
(
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_APPLY, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,
+ gtk.STOCK_APPLY,
+ gtk.RESPONSE_OK,
),
parent,
)
@@ -260,10 +277,7 @@ class AccountDialog(BaseDialog):
_('New Account'),
_('Create a new account'),
gtk.STOCK_DIALOG_INFO,
- (
- gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_ADD, gtk.RESPONSE_OK,
- ),
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_ADD, gtk.RESPONSE_OK),
parent,
)
@@ -339,7 +353,10 @@ class OtherDialog(BaseDialog):
Returns:
int or float:
"""
- def __init__(self, header, text='', unit_text='', icon=None, default=0, parent=None):
+
+ def __init__(
+ self, header, text='', unit_text='', icon=None, default=0, parent=None
+ ):
self.value_type = type(default)
if self.value_type not in (int, float):
raise TypeError('default value needs to be an int or float')
@@ -359,7 +376,9 @@ class OtherDialog(BaseDialog):
alignment_spacer = gtk.Alignment()
hbox.pack_start(alignment_spacer, True, True, 0)
alignment_spin = gtk.Alignment(1, 0.5, 1, 1)
- adjustment_spin = gtk.Adjustment(value=-1, lower=-1, upper=2097151, step_incr=1, page_incr=10)
+ adjustment_spin = gtk.Adjustment(
+ value=-1, lower=-1, upper=2097151, step_incr=1, page_incr=10
+ )
self.spinbutton = gtk.SpinButton(adjustment_spin)
self.spinbutton.set_value(default)
self.spinbutton.select_region(0, -1)
@@ -399,13 +418,15 @@ class PasswordDialog(BaseDialog):
When run(), it will return either a gtk.RESPONSE_CANCEL or a gtk.RESPONSE_OK.
"""
+
def __init__(self, password_msg='', parent=None):
"""
:param password_msg: the error message we got back from the server
:type password_msg: string
"""
super(PasswordDialog, self).__init__(
- _('Password Protected'), password_msg,
+ _('Password Protected'),
+ password_msg,
gtk.STOCK_DIALOG_AUTHENTICATION,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_CONNECT, gtk.RESPONSE_OK),
parent,
diff --git a/deluge/ui/gtkui/edittrackersdialog.py b/deluge/ui/gtkui/edittrackersdialog.py
index c3008cf44..bf1ba0ca9 100644
--- a/deluge/ui/gtkui/edittrackersdialog.py
+++ b/deluge/ui/gtkui/edittrackersdialog.py
@@ -83,17 +83,23 @@ class EditTrackersDialog(object):
self.gtkui_config = ConfigManager('gtkui.conf')
# Main dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.ui')
+ )
+ )
# add tracker dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.add.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.add.ui')
+ )
+ )
# edit tracker dialog
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.edit.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.edit.ui')
+ )
+ )
self.dialog = self.builder.get_object('edit_trackers_dialog')
self.treeview = self.builder.get_object('tracker_treeview')
@@ -116,10 +122,10 @@ class EditTrackersDialog(object):
# Create the columns
self.treeview.append_column(
- gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0),
+ gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0)
)
self.treeview.append_column(
- gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1),
+ gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1)
)
self.treeview.set_model(self.liststore)
@@ -135,9 +141,9 @@ class EditTrackersDialog(object):
# Get the trackers for this torrent
session = component.get('SessionProxy')
- session.get_torrent_status(
- self.torrent_id, ['trackers'],
- ).addCallback(self._on_get_torrent_status)
+ session.get_torrent_status(self.torrent_id, ['trackers']).addCallback(
+ self._on_get_torrent_status
+ )
client.force_call()
self.deferred = defer.Deferred()
@@ -169,6 +175,7 @@ class EditTrackersDialog(object):
tracker['tier'] = model.get_value(_iter, 0)
tracker['url'] = model.get_value(_iter, 1)
self.trackers.append(tracker)
+
self.liststore.foreach(each, None)
if self.old_trackers != self.trackers:
# Set the torrens trackers
diff --git a/deluge/ui/gtkui/files_tab.py b/deluge/ui/gtkui/files_tab.py
index 79cb66188..bfa9c8c46 100644
--- a/deluge/ui/gtkui/files_tab.py
+++ b/deluge/ui/gtkui/files_tab.py
@@ -15,14 +15,23 @@ import os.path
import gtk
import six.moves.cPickle as pickle
from gobject import TYPE_UINT64
-from gtk.gdk import ACTION_DEFAULT, ACTION_MOVE, BUTTON1_MASK, keyval_name # pylint: disable=ungrouped-imports
+from gtk.gdk import ( # pylint: disable=ungrouped-imports
+ ACTION_DEFAULT,
+ ACTION_MOVE,
+ BUTTON1_MASK,
+ keyval_name,
+)
import deluge.component as component
from deluge.common import open_file, show_file
from deluge.ui.client import client
from deluge.ui.common import FILE_PRIORITY
-from deluge.ui.gtkui.common import (listview_replace_treestore, load_pickled_state_file, reparent_iter,
- save_pickled_state_file)
+from deluge.ui.gtkui.common import (
+ listview_replace_treestore,
+ load_pickled_state_file,
+ reparent_iter,
+ save_pickled_state_file,
+)
from deluge.ui.gtkui.torrentdetails import Tab
from deluge.ui.gtkui.torrentview_data_funcs import cell_data_size
@@ -170,7 +179,7 @@ class FilesTab(Tab):
self.listview.connect('button-press-event', self._on_button_press_event)
self.listview.enable_model_drag_source(
- BUTTON1_MASK, [('text/plain', 0, 0)], ACTION_DEFAULT | ACTION_MOVE,
+ BUTTON1_MASK, [('text/plain', 0, 0)], ACTION_DEFAULT | ACTION_MOVE
)
self.listview.enable_model_drag_dest([('text/plain', 0, 0)], ACTION_DEFAULT)
@@ -180,9 +189,15 @@ class FilesTab(Tab):
component.get('MainWindow').connect_signals(self)
# Connect to various events from the daemon
- client.register_event_handler('TorrentFileRenamedEvent', self._on_torrentfilerenamed_event)
- client.register_event_handler('TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event)
- client.register_event_handler('TorrentRemovedEvent', self._on_torrentremoved_event)
+ client.register_event_handler(
+ 'TorrentFileRenamedEvent', self._on_torrentfilerenamed_event
+ )
+ client.register_event_handler(
+ 'TorrentFolderRenamedEvent', self._on_torrentfolderrenamed_event
+ )
+ client.register_event_handler(
+ 'TorrentRemovedEvent', self._on_torrentremoved_event
+ )
# Attempt to load state
self.load_state()
@@ -238,8 +253,13 @@ class FilesTab(Tab):
# Column is in wrong position
if cstate['position'] == 0:
self.listview.move_column_after(column, None)
- elif self.listview.get_columns()[cstate['position'] - 1].get_title() != cname:
- self.listview.move_column_after(column, self.listview.get_columns()[cstate['position'] - 1])
+ elif (
+ self.listview.get_columns()[cstate['position'] - 1].get_title()
+ != cname
+ ):
+ self.listview.move_column_after(
+ column, self.listview.get_columns()[cstate['position'] - 1]
+ )
def update(self):
# Get the first selected torrent
@@ -264,13 +284,16 @@ class FilesTab(Tab):
# We already have the files list stored, so just update the view
self.update_files()
- if self.torrent_id not in self.files_list or not self.files_list[self.torrent_id]:
+ if (
+ self.torrent_id not in self.files_list
+ or not self.files_list[self.torrent_id]
+ ):
# We need to get the files list
log.debug('Getting file list from core..')
status_keys += ['files']
component.get('SessionProxy').get_torrent_status(
- self.torrent_id, status_keys,
+ self.torrent_id, status_keys
).addCallback(self._on_get_torrent_status, self.torrent_id)
def clear(self):
@@ -325,12 +348,14 @@ class FilesTab(Tab):
if first_slash_index == -1:
files_storage[file_name] = (file_num, torrent_file)
else:
- file_name_chunk = file_name[:first_slash_index + 1]
+ file_name_chunk = file_name[: first_slash_index + 1]
if file_name_chunk not in files_storage:
files_storage[file_name_chunk] = {}
self.prepare_file(
- torrent_file, file_name[first_slash_index + 1:],
- file_num, files_storage[file_name_chunk],
+ torrent_file,
+ file_name[first_slash_index + 1 :],
+ file_num,
+ files_storage[file_name_chunk],
)
def add_files(self, parent_iter, split_files):
@@ -338,8 +363,7 @@ class FilesTab(Tab):
for key, value in split_files.items():
if key.endswith('/'):
chunk_iter = self.treestore.append(
- parent_iter,
- [key, 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY],
+ parent_iter, [key, 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY]
)
chunk_size = self.add_files(chunk_iter, value)
self.treestore.set(chunk_iter, 1, chunk_size)
@@ -359,6 +383,7 @@ class FilesTab(Tab):
def get_selected_files(self):
"""Returns a list of file indexes that are selected."""
+
def get_iter_children(itr, selected):
i = self.treestore.iter_children(itr)
while i:
@@ -398,9 +423,13 @@ class FilesTab(Tab):
parent = self.treestore.iter_parent(row)
while row:
if self.treestore.iter_children(row):
- completed_bytes += get_completed_bytes(self.treestore.iter_children(row))
+ completed_bytes += get_completed_bytes(
+ self.treestore.iter_children(row)
+ )
else:
- completed_bytes += self.treestore[row][1] * self.treestore[row][3] / 100
+ completed_bytes += (
+ self.treestore[row][1] * self.treestore[row][3] / 100
+ )
row = self.treestore.iter_next(row)
@@ -496,13 +525,13 @@ class FilesTab(Tab):
def on_menuitem_open_file_activate(self, menuitem):
if client.is_localhost:
component.get('SessionProxy').get_torrent_status(
- self.torrent_id, ['download_location'],
+ self.torrent_id, ['download_location']
).addCallback(self._on_open_file)
def on_menuitem_show_file_activate(self, menuitem):
if client.is_localhost:
component.get('SessionProxy').get_torrent_status(
- self.torrent_id, ['download_location'],
+ self.torrent_id, ['download_location']
).addCallback(self._on_show_file)
def _set_file_priorities_on_user_change(self, selected, priority):
@@ -520,26 +549,28 @@ class FilesTab(Tab):
file_priorities.sort()
priorities = [p[1] for p in file_priorities]
log.debug('priorities: %s', priorities)
- client.core.set_torrent_options([self.torrent_id], {'file_priorities': priorities})
+ client.core.set_torrent_options(
+ [self.torrent_id], {'file_priorities': priorities}
+ )
def on_menuitem_ignore_activate(self, menuitem):
self._set_file_priorities_on_user_change(
- self.get_selected_files(), FILE_PRIORITY['Ignore'],
+ self.get_selected_files(), FILE_PRIORITY['Ignore']
)
def on_menuitem_low_activate(self, menuitem):
self._set_file_priorities_on_user_change(
- self.get_selected_files(), FILE_PRIORITY['Low'],
+ self.get_selected_files(), FILE_PRIORITY['Low']
)
def on_menuitem_normal_activate(self, menuitem):
self._set_file_priorities_on_user_change(
- self.get_selected_files(), FILE_PRIORITY['Normal'],
+ self.get_selected_files(), FILE_PRIORITY['Normal']
)
def on_menuitem_high_activate(self, menuitem):
self._set_file_priorities_on_user_change(
- self.get_selected_files(), FILE_PRIORITY['High'],
+ self.get_selected_files(), FILE_PRIORITY['High']
)
def on_menuitem_expand_all_activate(self, menuitem):
@@ -586,7 +617,9 @@ class FilesTab(Tab):
parent_path = self.treestore[itr][0] + parent_path
itr = self.treestore.iter_parent(itr)
- client.core.rename_folder(self.torrent_id, parent_path + folder, parent_path + new_text)
+ client.core.rename_folder(
+ self.torrent_id, parent_path + folder, parent_path + new_text
+ )
self._editing_index = None
@@ -616,17 +649,28 @@ class FilesTab(Tab):
if old_name_parent != parent_path:
if parent_path:
for i, p in enumerate(parent_path):
- p_itr = self.get_iter_at_path('/'.join(parent_path[:i + 1]) + '/')
+ p_itr = self.get_iter_at_path('/'.join(parent_path[: i + 1]) + '/')
if not p_itr:
p_itr = self.get_iter_at_path('/'.join(parent_path[:i]) + '/')
p_itr = self.treestore.append(
- p_itr, [parent_path[i] + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY],
+ p_itr,
+ [
+ parent_path[i] + '/',
+ 0,
+ '',
+ 0,
+ 0,
+ -1,
+ gtk.STOCK_DIRECTORY,
+ ],
)
p_itr = self.get_iter_at_path('/'.join(parent_path) + '/')
old_name_itr = self.get_iter_at_path(old_name)
self.treestore.append(
p_itr,
- self.treestore.get(old_name_itr, *range(self.treestore.get_n_columns())),
+ self.treestore.get(
+ old_name_itr, *range(self.treestore.get_n_columns())
+ ),
)
self.treestore.remove(old_name_itr)
@@ -638,7 +682,7 @@ class FilesTab(Tab):
parent_iter = None
for f in new_folders:
parent_iter = self.treestore.append(
- parent_iter, [f + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY],
+ parent_iter, [f + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY]
)
child = self.get_iter_at_path(old_name)
self.treestore.append(
@@ -653,6 +697,7 @@ class FilesTab(Tab):
if model[itr][5] == index:
model[itr][0] = os.path.split(name)[-1]
return True
+
self.treestore.foreach(set_file_name, None)
def get_iter_at_path(self, filepath):
@@ -676,7 +721,9 @@ class FilesTab(Tab):
itr = self.treestore.iter_children(itr)
level += 1
continue
- elif (level + 1) == len(filepath) and ipath == (filepath[level] + '/' if is_dir else filepath[level]):
+ elif (level + 1) == len(filepath) and ipath == (
+ filepath[level] + '/' if is_dir else filepath[level]
+ ):
# This is the iter we've been searching for
path_iter = itr
break
@@ -734,18 +781,29 @@ class FilesTab(Tab):
return
if new_folder_iter:
# This means that a folder by this name already exists
- reparent_iter(self.treestore, self.treestore.iter_children(old_folder_iter), new_folder_iter)
+ reparent_iter(
+ self.treestore,
+ self.treestore.iter_children(old_folder_iter),
+ new_folder_iter,
+ )
else:
parent = old_folder_iter_parent
if new_split:
for ns in new_split[:-1]:
- parent = self.treestore.append(parent, [ns + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY])
+ parent = self.treestore.append(
+ parent, [ns + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY]
+ )
self.treestore[old_folder_iter][0] = new_split[-1] + '/'
reparent_iter(self.treestore, old_folder_iter, parent)
else:
child_itr = self.treestore.iter_children(old_folder_iter)
- reparent_iter(self.treestore, child_itr, old_folder_iter_parent, move_siblings=True)
+ reparent_iter(
+ self.treestore,
+ child_itr,
+ old_folder_iter_parent,
+ move_siblings=True,
+ )
# We need to check if the old_folder_iter no longer has children
# and if so, we delete it
@@ -759,7 +817,9 @@ class FilesTab(Tab):
paths = self.listview.get_selection().get_selected_rows()[1]
selection.set_text(pickle.dumps(paths, protocol=2))
- def _on_drag_data_received_data(self, treeview, context, x, y, selection, info, etime):
+ def _on_drag_data_received_data(
+ self, treeview, context, x, y, selection, info, etime
+ ):
try:
selected = pickle.loads(selection.data)
except pickle.UnpicklingError:
@@ -789,7 +849,8 @@ class FilesTab(Tab):
pp = self.treestore[itr][0] + pp
itr = self.treestore.iter_parent(itr)
client.core.rename_folder(
- self.torrent_id, pp + model[selected[0]][0],
+ self.torrent_id,
+ pp + model[selected[0]][0],
parent_path + model[selected[0]][0],
)
else:
diff --git a/deluge/ui/gtkui/filtertreeview.py b/deluge/ui/gtkui/filtertreeview.py
index 6bec3966c..ba9d9bb9e 100644
--- a/deluge/ui/gtkui/filtertreeview.py
+++ b/deluge/ui/gtkui/filtertreeview.py
@@ -40,10 +40,7 @@ STATE_PIX = {
'Moving': 'checking',
}
-TRACKER_PIX = {
- 'All': 'tracker_all',
- 'Error': 'tracker_warning',
-}
+TRACKER_PIX = {'All': 'tracker_all', 'Error': 'tracker_warning'}
FILTER_COLUMN = 5
@@ -91,8 +88,10 @@ class FilterTreeView(component.Component):
self.treeview.set_headers_visible(False)
self.treeview.set_level_indentation(-21)
# Force theme to use expander-size so we don't cut out entries due to indentation hack.
- gtk.rc_parse_string("""style "treeview-style" {GtkTreeView::expander-size = 7}
- class "GtkTreeView" style "treeview-style" """)
+ gtk.rc_parse_string(
+ """style "treeview-style" {GtkTreeView::expander-size = 7}
+ class "GtkTreeView" style "treeview-style" """
+ )
self.treeview.set_model(self.treestore)
self.treeview.get_selection().connect('changed', self.on_selection_changed)
@@ -107,7 +106,11 @@ class FilterTreeView(component.Component):
# filtertree menu
builder = gtk.Builder()
- builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join('glade', 'filtertree_menu.ui')))
+ builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'filtertree_menu.ui')
+ )
+ )
self.menu = builder.get_object('filtertree_menu')
builder.connect_signals(self)
@@ -119,21 +122,22 @@ class FilterTreeView(component.Component):
self.filters = {}
# initial order of state filter:
- self.cat_nodes['state'] = self.treestore.append(None, ['cat', 'state', _('States'), 0, None, False])
+ self.cat_nodes['state'] = self.treestore.append(
+ None, ['cat', 'state', _('States'), 0, None, False]
+ )
for state in ['All', 'Active'] + TORRENT_STATE:
self.update_row('state', state, 0, _(state))
self.cat_nodes['tracker_host'] = self.treestore.append(
- None, [
- 'cat', 'tracker_host',
- _('Trackers'), 0, None, False,
- ],
+ None, ['cat', 'tracker_host', _('Trackers'), 0, None, False]
)
self.update_row('tracker_host', 'All', 0, _('All'))
self.update_row('tracker_host', 'Error', 0, _('Error'))
self.update_row('tracker_host', '', 0, _('None'))
- self.cat_nodes['owner'] = self.treestore.append(None, ['cat', 'owner', _('Owner'), 0, None, False])
+ self.cat_nodes['owner'] = self.treestore.append(
+ None, ['cat', 'owner', _('Owner'), 0, None, False]
+ )
self.update_row('owner', 'localclient', 0, _('Admin'))
self.update_row('owner', '', 0, _('None'))
@@ -157,7 +161,9 @@ class FilterTreeView(component.Component):
label = _(cat)
if cat == 'label':
label = _('Labels')
- self.cat_nodes[cat] = self.treestore.append(None, ['cat', cat, label, 0, None, False])
+ self.cat_nodes[cat] = self.treestore.append(
+ None, ['cat', cat, label, 0, None, False]
+ )
# update rows
visible_filters = []
@@ -168,7 +174,11 @@ class FilterTreeView(component.Component):
# hide root-categories not returned by core-part of the plugin.
for cat in self.cat_nodes:
- self.treestore.set_value(self.cat_nodes[cat], FILTER_COLUMN, True if cat in filter_items else False)
+ self.treestore.set_value(
+ self.cat_nodes[cat],
+ FILTER_COLUMN,
+ True if cat in filter_items else False,
+ )
# hide items not returned by core-plugin.
for f in self.filters:
@@ -201,7 +211,9 @@ class FilterTreeView(component.Component):
elif not label and value:
label = _(value)
- row = self.treestore.append(self.cat_nodes[cat], [cat, value, label, count, pix, True])
+ row = self.treestore.append(
+ self.cat_nodes[cat], [cat, value, label, count, pix, True]
+ )
self.filters[(cat, value)] = row
if cat == 'tracker_host' and value not in ('All', 'Error') and value:
@@ -284,8 +296,7 @@ class FilterTreeView(component.Component):
if not self.config['sidebar_show_owners']:
hide_cat.append('owner')
client.core.get_filter_tree(
- self.config['sidebar_show_zero'],
- hide_cat,
+ self.config['sidebar_show_zero'], hide_cat
).addCallback(self.cb_update_filter_tree)
except Exception as ex:
log.debug(ex)
@@ -336,7 +347,7 @@ class FilterTreeView(component.Component):
def set_menu_sensitivity(self):
# select-all/pause/resume
- sensitive = (self.cat != 'cat' and self.count != 0)
+ sensitive = self.cat != 'cat' and self.count != 0
for item in self.default_menu_items:
item.set_sensitive(sensitive)
diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py
index 0468baa86..16bde8454 100644
--- a/deluge/ui/gtkui/gtkui.py
+++ b/deluge/ui/gtkui/gtkui.py
@@ -17,6 +17,7 @@ import sys
import time
import pygtk # isort:skip (Required before gtk import).
+
pygtk.require('2.0') # NOQA: E402
# isort:imports-thirdparty
@@ -36,7 +37,13 @@ except ReactorAlreadyInstalledError as ex:
# isort:imports-firstparty
import deluge.component as component
-from deluge.common import fsize, fspeed, get_default_download_dir, osx_check, windows_check
+from deluge.common import (
+ fsize,
+ fspeed,
+ get_default_download_dir,
+ osx_check,
+ windows_check,
+)
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.error import DaemonRunningError
from deluge.ui.client import client
@@ -68,6 +75,7 @@ log = logging.getLogger(__name__)
try:
from setproctitle import setproctitle, getproctitle
except ImportError:
+
def setproctitle(title):
return
@@ -149,10 +157,12 @@ class GtkUI(object):
if windows_check():
from win32api import SetConsoleCtrlHandler
+
SetConsoleCtrlHandler(on_die, True)
log.debug('Win32 "die" handler registered')
elif osx_check() and WINDOWING == 'quartz':
import gtkosx_application
+
self.osxapp = gtkosx_application.gtkosx_application_get()
self.osxapp.connect('NSApplicationWillTerminate', on_die)
log.debug('OSX quartz "die" handler registered')
@@ -202,13 +212,16 @@ class GtkUI(object):
self.addtorrentdialog = AddTorrentDialog()
if osx_check() and WINDOWING == 'quartz':
+
def nsapp_open_file(osxapp, filename):
# Ignore command name which is raised at app launch (python opening main script).
if filename == sys.argv[0]:
return True
process_args([filename])
+
self.osxapp.connect('NSApplicationOpenFile', nsapp_open_file)
from deluge.ui.gtkui.menubar_osx import menubar_osx
+
menubar_osx(self, self.osxapp)
self.osxapp.ready()
@@ -286,7 +299,13 @@ class GtkUI(object):
self.daemon_bps = (t, sent, recv)
sent_rate = fspeed(delta_sent / delta_time)
recv_rate = fspeed(delta_recv / delta_time)
- log.debug('RPC: Sent %s (%s) Recv %s (%s)', fsize(sent), sent_rate, fsize(recv), recv_rate)
+ log.debug(
+ 'RPC: Sent %s (%s) Recv %s (%s)',
+ fsize(sent),
+ sent_rate,
+ fsize(recv),
+ recv_rate,
+ )
def _on_reactor_start(self):
log.debug('_on_reactor_start')
@@ -301,25 +320,25 @@ class GtkUI(object):
except DaemonRunningError:
err_msg = _(
'A Deluge daemon (deluged) is already running.\n'
- 'To use Standalone mode, stop local daemon and restart Deluge.',
+ 'To use Standalone mode, stop local daemon and restart Deluge.'
)
except ImportError as ex:
if 'No module named libtorrent' in ex.message:
err_msg = _(
'Only Thin Client mode is available because libtorrent is not installed.\n'
- 'To use Standalone mode, please install libtorrent package.',
+ 'To use Standalone mode, please install libtorrent package.'
)
else:
log.exception(ex)
err_msg = _(
'Only Thin Client mode is available due to unknown Import Error.\n'
- 'To use Standalone mode, please see logs for error details.',
+ 'To use Standalone mode, please see logs for error details.'
)
except Exception as ex:
log.exception(ex)
err_msg = _(
'Only Thin Client mode is available due to unknown Import Error.\n'
- 'To use Standalone mode, please see logs for error details.',
+ 'To use Standalone mode, please see logs for error details.'
)
else:
component.start()
@@ -347,6 +366,7 @@ class GtkUI(object):
# Check to see if we need to start the localhost daemon
if self.config['autostart_localhost']:
+
def on_localhost_status(status_info, port):
if status_info[1] == 'Offline':
log.debug('Autostarting localhost: %s', host_config[0:3])
diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py
index 373d9e39f..a2e348028 100644
--- a/deluge/ui/gtkui/ipcinterface.py
+++ b/deluge/ui/gtkui/ipcinterface.py
@@ -42,7 +42,6 @@ log = logging.getLogger(__name__)
class IPCProtocolServer(Protocol):
-
def __init__(self):
pass
@@ -55,7 +54,6 @@ class IPCProtocolServer(Protocol):
class IPCProtocolClient(Protocol):
-
def __init__(self):
pass
@@ -93,12 +91,14 @@ class IPCInterface(component.Component):
import win32event
import win32api
import winerror
+
self.mutex = win32event.CreateMutex(None, False, 'deluge')
if win32api.GetLastError() != winerror.ERROR_ALREADY_EXISTS:
# Create listen socket
self.factory = Factory()
self.factory.protocol = IPCProtocolServer
import random
+
port = random.randrange(20000, 65535)
self.listener = reactor.listenTCP(port, self.factory)
# Store the port number in the socket file
@@ -124,6 +124,7 @@ class IPCInterface(component.Component):
lockfile = socket + '.lock'
log.debug('Checking if lockfile exists: %s', lockfile)
if os.path.lexists(lockfile):
+
def delete_lockfile():
log.debug('Delete stale lockfile.')
try:
@@ -138,14 +139,18 @@ class IPCInterface(component.Component):
delete_lockfile()
else:
if restart_tempfile:
- log.warning('Found running PID but it is not a Deluge process, removing lockfile...')
+ log.warning(
+ 'Found running PID but it is not a Deluge process, removing lockfile...'
+ )
delete_lockfile()
try:
self.factory = Factory()
self.factory.protocol = IPCProtocolServer
self.listener = reactor.listenUNIX(socket, self.factory, wantPID=True)
except twisted.internet.error.CannotListenError as ex:
- log.info('Deluge is already running! Sending arguments to running instance...')
+ log.info(
+ 'Deluge is already running! Sending arguments to running instance...'
+ )
self.factory = IPCClientFactory()
self.factory.args = args
reactor.connectUNIX(socket, self.factory, checkPID=True)
@@ -153,6 +158,7 @@ class IPCInterface(component.Component):
if self.factory.stop:
log.info('Success sending arguments to running Deluge.')
from gtk.gdk import notify_startup_complete
+
notify_startup_complete()
sys.exit(0)
else:
@@ -170,6 +176,7 @@ class IPCInterface(component.Component):
def shutdown(self):
if windows_check():
import win32api
+
win32api.CloseHandle(self.mutex)
if self.listener:
return self.listener.stopListening()
diff --git a/deluge/ui/gtkui/listview.py b/deluge/ui/gtkui/listview.py
index e1d42659c..e9a2951c4 100644
--- a/deluge/ui/gtkui/listview.py
+++ b/deluge/ui/gtkui/listview.py
@@ -18,7 +18,9 @@ from gtk.gdk import Event # pylint: disable=ungrouped-imports
from deluge.common import decode_bytes
from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file
-signal_new('button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,))
+signal_new(
+ 'button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,)
+)
log = logging.getLogger(__name__)
@@ -29,6 +31,7 @@ class ListViewColumnState: # pylint: disable=old-style-class
Note: This must be old style class to avoid breaking existing user state file.
"""
+
def __init__(self, name, position, width, visible, sort, sort_order):
self.name = name
self.position = position
@@ -46,6 +49,7 @@ class ListView(object):
class ListViewColumn(object):
"""Holds information regarding a column in the ListView"""
+
def __init__(self, name, column_indices):
# Name is how a column is identified and is also the header
self.name = name
@@ -79,9 +83,9 @@ class ListView(object):
Most of the code of this class comes from Quod Libet (http://www.sacredchao.net/quodlibet)
"""
- def __init__(self, title=None, cell_renderer=None, ** args):
+ def __init__(self, title=None, cell_renderer=None, **args):
""" Constructor, see gtk.TreeViewColumn """
- gtk.TreeViewColumn.__init__(self, title, cell_renderer, ** args)
+ gtk.TreeViewColumn.__init__(self, title, cell_renderer, **args)
label = gtk.Label(title)
self.set_widget(label)
label.show()
@@ -114,7 +118,9 @@ class ListView(object):
# Set data function to None to prevent unecessary calls when column is hidden
self.set_cell_data_func(self.cell_renderer, None, func_data=None)
else:
- self.set_cell_data_func(self.cell_renderer, self.data_func, self.data_func_data)
+ self.set_cell_data_func(
+ self.cell_renderer, self.data_func, self.data_func_data
+ )
def set_col_attributes(self, renderer, add=True, **kw):
if add is True:
@@ -177,9 +183,7 @@ class ListView(object):
must be called after listview.create_new_liststore
"""
model_filter = self.liststore.filter_new()
- model_filter.set_visible_column(
- self.columns['filter'].column_indices[0],
- )
+ model_filter.set_visible_column(self.columns['filter'].column_indices[0])
self.model_filter = gtk.TreeModelSort(model_filter)
self.model_filter.connect('sort-column-changed', self.on_model_sort_changed)
self.model_filter.connect('row-inserted', self.on_model_row_inserted)
@@ -190,12 +194,17 @@ class ListView(object):
def set_model_sort(self):
column_state = self.get_sort_column_from_state()
if column_state:
- self.treeview.get_model().set_sort_column_id(column_state.sort, column_state.sort_order)
+ self.treeview.get_model().set_sort_column_id(
+ column_state.sort, column_state.sort_order
+ )
# Using the default sort column
elif self.default_sort_column_id:
- self.model_filter.set_sort_column_id(self.default_sort_column_id, gtk.SORT_ASCENDING)
+ self.model_filter.set_sort_column_id(
+ self.default_sort_column_id, gtk.SORT_ASCENDING
+ )
self.model_filter.set_default_sort_func(
- self.generic_sort_func, self.get_column_index('Added')[0])
+ self.generic_sort_func, self.get_column_index('Added')[0]
+ )
def get_sort_column_from_state(self):
"""Find the first (should only be one) state with sort enabled"""
@@ -212,12 +221,13 @@ class ListView(object):
def record_position(model, path, _iter, data):
self.last_sort_order[model[_iter][self.unique_column_id]] = path[0]
+
model.foreach(record_position, None)
def on_model_row_inserted(self, model, path, _iter):
if self.unique_column_id:
self.last_sort_order.setdefault(
- model[_iter][self.unique_column_id], len(model) - 1,
+ model[_iter][self.unique_column_id], len(model) - 1
)
def stabilize_sort_func(self, sort_func):
@@ -228,14 +238,14 @@ class ListView(object):
unique2 = model[iter2][self.unique_column_id]
if unique1 in self.last_sort_order and unique2 in self.last_sort_order:
result = cmp(
- self.last_sort_order[unique1],
- self.last_sort_order[unique2],
+ self.last_sort_order[unique1], self.last_sort_order[unique2]
)
# If all else fails, fall back to sorting by unique column
if result == 0:
result = cmp(unique1, unique2)
return result
+
return stabilized
def generic_sort_func(self, model, iter1, iter2, data):
@@ -245,9 +255,7 @@ class ListView(object):
for column in self.columns.values():
sort_func = column.sort_func or self.generic_sort_func
self.model_filter.set_sort_func(
- column.sort_id,
- self.stabilize_sort_func(sort_func),
- column.sort_id,
+ column.sort_id, self.stabilize_sort_func(sort_func), column.sort_id
)
def create_column_state(self, column, position=None):
@@ -264,8 +272,12 @@ class ListView(object):
sort = sort_id
return ListViewColumnState(
- column.get_title(), position, column.get_width(),
- column.get_visible(), sort, int(column.get_sort_order()),
+ column.get_title(),
+ position,
+ column.get_width(),
+ column.get_visible(),
+ sort,
+ int(column.get_sort_order()),
)
def save_state(self, filename):
@@ -402,45 +414,50 @@ class ListView(object):
if add:
tree_column.pack_start(column.renderer, True)
tree_column.set_col_attributes(
- column.renderer, add=add,
- text=column.column_indices[column.text_index],
+ column.renderer, add=add, text=column.column_indices[column.text_index]
)
elif column.column_type == 'bool':
if add:
tree_column.pack_start(column.renderer, True)
- tree_column.set_col_attributes(column.renderer, active=column.column_indices[0])
+ tree_column.set_col_attributes(
+ column.renderer, active=column.column_indices[0]
+ )
elif column.column_type == 'func':
if add:
tree_column.pack_start(column.renderer, True)
indice_arg = column.column_indices[0]
if len(column.column_indices) > 1:
indice_arg = tuple(column.column_indices)
- tree_column.set_cell_data_func(column.renderer, column.data_func, indice_arg)
+ tree_column.set_cell_data_func(
+ column.renderer, column.data_func, indice_arg
+ )
elif column.column_type == 'progress':
if add:
tree_column.pack_start(column.renderer, True)
if column.data_func is None:
tree_column.set_col_attributes(
- column.renderer, add=add,
+ column.renderer,
+ add=add,
text=column.column_indices[column.text_index],
value=column.column_indices[column.value_index],
)
else:
tree_column.set_cell_data_func(
- column.renderer, column.data_func,
- tuple(column.column_indices),
+ column.renderer, column.data_func, tuple(column.column_indices)
)
elif column.column_type == 'texticon':
if add:
tree_column.pack_start(column.renderer[column.pixbuf_index], False)
tree_column.pack_start(column.renderer[column.text_index], True)
tree_column.set_col_attributes(
- column.renderer[column.text_index], add=add,
+ column.renderer[column.text_index],
+ add=add,
text=column.column_indices[column.text_index],
)
if column.data_func is not None:
tree_column.set_cell_data_func(
- column.renderer[column.pixbuf_index], column.data_func,
+ column.renderer[column.pixbuf_index],
+ column.data_func,
column.column_indices[column.pixbuf_index],
)
return True
@@ -483,10 +500,24 @@ class ListView(object):
return
def add_column(
- self, header, render, col_types, hidden, position,
- status_field, sortid, text=0, value=0, pixbuf=0, function=None,
- column_type=None, sort_func=None, tooltip=None, default=True,
- unique=False, default_sort=False,
+ self,
+ header,
+ render,
+ col_types,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ text=0,
+ value=0,
+ pixbuf=0,
+ function=None,
+ column_type=None,
+ sort_func=None,
+ tooltip=None,
+ default=True,
+ unique=False,
+ default_sort=False,
):
"""Adds a column to the ListView"""
# Add the column types to liststore_columns
@@ -544,10 +575,7 @@ class ListView(object):
column.set_min_width(20)
column.set_reorderable(True)
column.set_visible(not hidden)
- column.connect(
- 'button-press-event',
- self.on_treeview_header_right_clicked,
- )
+ column.connect('button-press-event', self.on_treeview_header_right_clicked)
if tooltip:
column.get_widget().set_tooltip_markup(tooltip)
@@ -586,58 +614,116 @@ class ListView(object):
return True
def add_text_column(
- self, header, col_type=str, hidden=False, position=None,
- status_field=None, sortid=0, column_type='text',
- sort_func=None, tooltip=None, default=True, unique=False,
+ self,
+ header,
+ col_type=str,
+ hidden=False,
+ position=None,
+ status_field=None,
+ sortid=0,
+ column_type='text',
+ sort_func=None,
+ tooltip=None,
+ default=True,
+ unique=False,
default_sort=False,
):
"""Add a text column to the listview. Only the header name is required.
"""
render = gtk.CellRendererText()
self.add_column(
- header, render, col_type, hidden, position,
- status_field, sortid, column_type=column_type,
- sort_func=sort_func, tooltip=tooltip, default=default,
- unique=unique, default_sort=default_sort,
+ header,
+ render,
+ col_type,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ column_type=column_type,
+ sort_func=sort_func,
+ tooltip=tooltip,
+ default=default,
+ unique=unique,
+ default_sort=default_sort,
)
return True
def add_bool_column(
- self, header, col_type=bool, hidden=False,
- position=None, status_field=None, sortid=0,
- column_type='bool', tooltip=None, default=True,
+ self,
+ header,
+ col_type=bool,
+ hidden=False,
+ position=None,
+ status_field=None,
+ sortid=0,
+ column_type='bool',
+ tooltip=None,
+ default=True,
):
"""Add a bool column to the listview"""
render = gtk.CellRendererToggle()
self.add_column(
- header, render, col_type, hidden, position,
- status_field, sortid, column_type=column_type,
- tooltip=tooltip, default=default,
+ header,
+ render,
+ col_type,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ column_type=column_type,
+ tooltip=tooltip,
+ default=default,
)
def add_func_column(
- self, header, function, col_types, sortid=0,
- hidden=False, position=None, status_field=None,
- column_type='func', sort_func=None, tooltip=None, default=True,
+ self,
+ header,
+ function,
+ col_types,
+ sortid=0,
+ hidden=False,
+ position=None,
+ status_field=None,
+ column_type='func',
+ sort_func=None,
+ tooltip=None,
+ default=True,
):
"""Add a function column to the listview. Need a header name, the
function and the column types."""
render = gtk.CellRendererText()
self.add_column(
- header, render, col_types, hidden, position,
- status_field, sortid, column_type=column_type,
- function=function, sort_func=sort_func, tooltip=tooltip, default=default,
+ header,
+ render,
+ col_types,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ column_type=column_type,
+ function=function,
+ sort_func=sort_func,
+ tooltip=tooltip,
+ default=default,
)
return True
def add_progress_column(
- self, header, col_types=None, sortid=0,
- hidden=False, position=None, status_field=None,
- function=None, column_type='progress',
- tooltip=None, sort_func=None, default=True,
+ self,
+ header,
+ col_types=None,
+ sortid=0,
+ hidden=False,
+ position=None,
+ status_field=None,
+ function=None,
+ column_type='progress',
+ tooltip=None,
+ sort_func=None,
+ default=True,
):
"""Add a progress column to the listview."""
@@ -645,19 +731,38 @@ class ListView(object):
col_types = [float, str]
render = gtk.CellRendererProgress()
self.add_column(
- header, render, col_types, hidden, position,
- status_field, sortid, function=function,
- column_type=column_type, value=0, text=1,
- tooltip=tooltip, sort_func=sort_func, default=default,
+ header,
+ render,
+ col_types,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ function=function,
+ column_type=column_type,
+ value=0,
+ text=1,
+ tooltip=tooltip,
+ sort_func=sort_func,
+ default=default,
)
return True
def add_texticon_column(
- self, header, col_types=None, sortid=1,
- hidden=False, position=None, status_field=None,
- column_type='texticon', function=None, sort_func=None,
- tooltip=None, default=True, default_sort=False,
+ self,
+ header,
+ col_types=None,
+ sortid=1,
+ hidden=False,
+ position=None,
+ status_field=None,
+ column_type='texticon',
+ function=None,
+ sort_func=None,
+ tooltip=None,
+ default=True,
+ default_sort=False,
):
"""Adds a texticon column to the listview."""
if col_types is None:
@@ -666,10 +771,21 @@ class ListView(object):
render2 = gtk.CellRendererText()
self.add_column(
- header, (render1, render2), col_types, hidden, position,
- status_field, sortid, column_type=column_type,
- function=function, pixbuf=0, text=1, tooltip=tooltip,
- sort_func=sort_func, default=default, default_sort=default_sort,
+ header,
+ (render1, render2),
+ col_types,
+ hidden,
+ position,
+ status_field,
+ sortid,
+ column_type=column_type,
+ function=function,
+ pixbuf=0,
+ text=1,
+ tooltip=tooltip,
+ sort_func=sort_func,
+ default=default,
+ default_sort=default_sort,
)
return True
@@ -708,7 +824,9 @@ class ListView(object):
continue
column = find_column(col_state.name)
if not column:
- log.debug('Could not find column matching "%s" on state.', col_state.name)
+ log.debug(
+ 'Could not find column matching "%s" on state.', col_state.name
+ )
# The cases where I've found that the column could not be found
# is when not using the english locale, ie, the default one, or
# when changing locales between runs.
diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py
index c68d0a15e..aef39219b 100644
--- a/deluge/ui/gtkui/mainwindow.py
+++ b/deluge/ui/gtkui/mainwindow.py
@@ -15,7 +15,12 @@ import os.path
from hashlib import sha1 as sha
import gtk
-from gtk.gdk import ACTION_COPY, WINDOW_STATE_ICONIFIED, WINDOW_STATE_MAXIMIZED, WINDOW_STATE_WITHDRAWN
+from gtk.gdk import (
+ ACTION_COPY,
+ WINDOW_STATE_ICONIFIED,
+ WINDOW_STATE_MAXIMIZED,
+ WINDOW_STATE_WITHDRAWN,
+)
from twisted.internet import reactor
from twisted.internet.error import ReactorNotRunning
@@ -42,8 +47,8 @@ class _GtkBuilderSignalsHolder(object):
for name, handler in mapping_or_class.items():
if hasattr(self, name):
raise RuntimeError(
- 'A handler for signal %r has already been registered: %s' %
- (name, getattr(self, name)),
+ 'A handler for signal %r has already been registered: %s'
+ % (name, getattr(self, name))
)
setattr(self, name, handler)
else:
@@ -51,8 +56,10 @@ class _GtkBuilderSignalsHolder(object):
if not name.startswith('on_'):
continue
if hasattr(self, name):
- raise RuntimeError('A handler for signal %r has already been registered: %s' %
- (name, getattr(self, name)))
+ raise RuntimeError(
+ 'A handler for signal %r has already been registered: %s'
+ % (name, getattr(self, name))
+ )
setattr(self, name, getattr(mapping_or_class, name))
@@ -69,22 +76,28 @@ class MainWindow(component.Component):
# Think about splitting up mainwindow gtkbuilder file into the necessary parts
# to avoid GtkBuilder monkey patch. Those parts would then need adding to mainwindow 'by hand'.
self.gtk_builder_signals_holder = _GtkBuilderSignalsHolder()
- self.main_builder.prev_connect_signals = copy.deepcopy(self.main_builder.connect_signals)
+ self.main_builder.prev_connect_signals = copy.deepcopy(
+ self.main_builder.connect_signals
+ )
def patched_connect_signals(*a, **k):
raise RuntimeError(
'In order to connect signals to this GtkBuilder instance please use '
- '"component.get(\'MainWindow\').connect_signals()"',
+ '"component.get(\'MainWindow\').connect_signals()"'
)
+
self.main_builder.connect_signals = patched_connect_signals
# Get Gtk Builder files Main Window, New release dialog, and Tabs.
for filename in (
- 'main_window.ui', 'main_window.new_release.ui', 'main_window.tabs.ui',
- 'main_window.tabs.menu_file.ui', 'main_window.tabs.menu_peer.ui',
+ 'main_window.ui',
+ 'main_window.new_release.ui',
+ 'main_window.tabs.ui',
+ 'main_window.tabs.menu_file.ui',
+ 'main_window.tabs.menu_peer.ui',
):
self.main_builder.add_from_file(
- resource_filename('deluge.ui.gtkui', os.path.join('glade', filename)),
+ resource_filename('deluge.ui.gtkui', os.path.join('glade', filename))
)
self.window = self.main_builder.get_object('main_window')
@@ -102,7 +115,9 @@ class MainWindow(component.Component):
self.is_minimized = False
self.restart = False
- self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 80)], ACTION_COPY)
+ self.window.drag_dest_set(
+ gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 80)], ACTION_COPY
+ )
# Connect events
self.window.connect('window-state-event', self.on_window_state_event)
@@ -112,9 +127,13 @@ class MainWindow(component.Component):
self.vpaned.connect('notify::position', self.on_vpaned_position_event)
self.window.connect('expose-event', self.on_expose_event)
- self.config.register_set_function('show_rate_in_title', self._on_set_show_rate_in_title, apply_now=False)
+ self.config.register_set_function(
+ 'show_rate_in_title', self._on_set_show_rate_in_title, apply_now=False
+ )
- client.register_event_handler('NewVersionAvailableEvent', self.on_newversionavailable_event)
+ client.register_event_handler(
+ 'NewVersionAvailableEvent', self.on_newversionavailable_event
+ )
def connect_signals(self, mapping_or_class):
self.gtk_builder_signals_holder.connect_signals(mapping_or_class)
@@ -123,7 +142,7 @@ class MainWindow(component.Component):
self.main_builder.prev_connect_signals(self.gtk_builder_signals_holder)
self.vpaned.set_position(self.initial_vpaned_position)
if not (
- self.config['start_in_tray'] and self.config['enable_system_tray']
+ self.config['start_in_tray'] and self.config['enable_system_tray']
) and not self.window.get_property('visible'):
log.debug('Showing window')
self.show()
@@ -140,7 +159,9 @@ class MainWindow(component.Component):
component.pause(self.child_components)
# Store the x, y positions for when we restore the window
- self.config['window_x_pos'], self.config['window_y_pos'] = self.window.get_position()
+ self.config['window_x_pos'], self.config[
+ 'window_y_pos'
+ ] = self.window.get_position()
self.window.hide()
def present(self):
@@ -155,8 +176,12 @@ class MainWindow(component.Component):
def on_dialog_response(response_id):
if response_id == gtk.RESPONSE_OK:
- if self.config['tray_password'] == sha(dialog.get_password()).hexdigest():
+ if (
+ self.config['tray_password']
+ == sha(dialog.get_password()).hexdigest()
+ ):
restore()
+
dialog.run().addCallback(on_dialog_response)
else:
restore()
@@ -202,14 +227,21 @@ class MainWindow(component.Component):
def on_dialog_response(response_id):
if response_id == gtk.RESPONSE_OK:
- if self.config['tray_password'] == sha(dialog.get_password()).hexdigest():
+ if (
+ self.config['tray_password']
+ == sha(dialog.get_password()).hexdigest()
+ ):
quit_gtkui()
+
dialog.run().addCallback(on_dialog_response)
else:
quit_gtkui()
def load_window_state(self):
- if self.config['window_x_pos'] == -32000 or self.config['window_x_pos'] == -32000:
+ if (
+ self.config['window_x_pos'] == -32000
+ or self.config['window_x_pos'] == -32000
+ ):
self.config['window_x_pos'] = self.config['window_y_pos'] = 0
self.window.move(self.config['window_x_pos'], self.config['window_y_pos'])
@@ -219,7 +251,9 @@ class MainWindow(component.Component):
def on_window_configure_event(self, widget, event):
if not self.config['window_maximized'] and self.visible:
- self.config['window_x_pos'], self.config['window_y_pos'] = self.window.get_position()
+ self.config['window_x_pos'], self.config[
+ 'window_y_pos'
+ ] = self.window.get_position()
self.config['window_width'] = event.width
self.config['window_height'] = event.height
@@ -253,7 +287,9 @@ class MainWindow(component.Component):
def on_vpaned_position_event(self, obj, param):
self.config['window_pane_position'] = self.vpaned.get_position()
- def on_drag_data_received_event(self, widget, drag_context, x, y, selection_data, info, timestamp):
+ def on_drag_data_received_event(
+ self, widget, drag_context, x, y, selection_data, info, timestamp
+ ):
log.debug('Selection(s) dropped on main window %s', selection_data.get_text())
if selection_data.get_uris():
process_args(selection_data.get_uris())
@@ -270,12 +306,19 @@ class MainWindow(component.Component):
def update(self):
# Update the window title
def _on_get_session_status(status):
- download_rate = fspeed(status['payload_download_rate'], precision=0, shortform=True)
- upload_rate = fspeed(status['payload_upload_rate'], precision=0, shortform=True)
- self.window.set_title(_('D: %s U: %s - Deluge' % (download_rate, upload_rate)))
+ download_rate = fspeed(
+ status['payload_download_rate'], precision=0, shortform=True
+ )
+ upload_rate = fspeed(
+ status['payload_upload_rate'], precision=0, shortform=True
+ )
+ self.window.set_title(
+ _('D: %s U: %s - Deluge' % (download_rate, upload_rate))
+ )
+
if self.config['show_rate_in_title']:
client.core.get_session_status(
- ['payload_download_rate', 'payload_upload_rate'],
+ ['payload_download_rate', 'payload_upload_rate']
).addCallback(_on_get_session_status)
def _on_set_show_rate_in_title(self, key, value):
@@ -287,6 +330,7 @@ class MainWindow(component.Component):
def on_newversionavailable_event(self, new_version):
if self.config['show_new_releases']:
from deluge.ui.gtkui.new_release_dialog import NewReleaseDialog
+
reactor.callLater(5.0, NewReleaseDialog().show, new_version)
def is_on_active_workspace(self):
diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py
index a08ce972c..f54f81e09 100644
--- a/deluge/ui/gtkui/menubar.py
+++ b/deluge/ui/gtkui/menubar.py
@@ -27,7 +27,6 @@ log = logging.getLogger(__name__)
class MenuBar(component.Component):
-
def __init__(self):
log.debug('MenuBar init..')
component.Component.__init__(self, 'MenuBar')
@@ -37,17 +36,23 @@ class MenuBar(component.Component):
self.builder = gtk.Builder()
# Get the torrent menu from the gtk builder file
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.ui')
+ )
+ )
# Get the torrent options menu from the gtk builder file
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.options.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.options.ui')
+ )
+ )
# Get the torrent queue menu from the gtk builder file
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.queue.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'torrent_menu.queue.ui')
+ )
+ )
# Attach queue torrent menu
torrent_queue_menu = self.builder.get_object('queue_torrent_menu')
@@ -56,12 +61,18 @@ class MenuBar(component.Component):
torrent_options_menu = self.builder.get_object('options_torrent_menu')
self.builder.get_object('menuitem_options').set_submenu(torrent_options_menu)
- self.builder.get_object('download-limit-image').set_from_file(deluge.common.get_pixmap('downloading16.png'))
- self.builder.get_object('upload-limit-image').set_from_file(deluge.common.get_pixmap('seeding16.png'))
+ self.builder.get_object('download-limit-image').set_from_file(
+ deluge.common.get_pixmap('downloading16.png')
+ )
+ self.builder.get_object('upload-limit-image').set_from_file(
+ deluge.common.get_pixmap('seeding16.png')
+ )
for menuitem in (
- 'menuitem_down_speed', 'menuitem_up_speed',
- 'menuitem_max_connections', 'menuitem_upload_slots',
+ 'menuitem_down_speed',
+ 'menuitem_up_speed',
+ 'menuitem_max_connections',
+ 'menuitem_upload_slots',
):
submenu = gtk.Menu()
item = gtk.MenuItem(_('Set Unlimited'))
@@ -103,12 +114,24 @@ class MenuBar(component.Component):
self.menu_torrent.set_submenu(self.torrentmenu)
# Make sure the view menuitems are showing the correct active state
- self.main_builder.get_object('menuitem_toolbar').set_active(self.config['show_toolbar'])
- self.main_builder.get_object('menuitem_sidebar').set_active(self.config['show_sidebar'])
- self.main_builder.get_object('menuitem_statusbar').set_active(self.config['show_statusbar'])
- self.main_builder.get_object('sidebar_show_zero').set_active(self.config['sidebar_show_zero'])
- self.main_builder.get_object('sidebar_show_trackers').set_active(self.config['sidebar_show_trackers'])
- self.main_builder.get_object('sidebar_show_owners').set_active(self.config['sidebar_show_owners'])
+ self.main_builder.get_object('menuitem_toolbar').set_active(
+ self.config['show_toolbar']
+ )
+ self.main_builder.get_object('menuitem_sidebar').set_active(
+ self.config['show_sidebar']
+ )
+ self.main_builder.get_object('menuitem_statusbar').set_active(
+ self.config['show_statusbar']
+ )
+ self.main_builder.get_object('sidebar_show_zero').set_active(
+ self.config['sidebar_show_zero']
+ )
+ self.main_builder.get_object('sidebar_show_trackers').set_active(
+ self.config['sidebar_show_trackers']
+ )
+ self.main_builder.get_object('sidebar_show_owners').set_active(
+ self.config['sidebar_show_owners']
+ )
# Connect main window Signals #
self.mainwindow.connect_signals(self)
@@ -116,19 +139,14 @@ class MenuBar(component.Component):
# Connect menubar signals
self.builder.connect_signals(self)
- self.change_sensitivity = [
- 'menuitem_addtorrent',
- ]
+ self.change_sensitivity = ['menuitem_addtorrent']
def start(self):
for widget in self.change_sensitivity:
self.main_builder.get_object(widget).set_sensitive(True)
# Only show open_folder menuitem and separator if connected to a localhost daemon.
- localhost_items = [
- 'menuitem_open_folder',
- 'separator4',
- ]
+ localhost_items = ['menuitem_open_folder', 'separator4']
if client.is_localhost():
for widget in localhost_items:
self.builder.get_object(widget).show()
@@ -138,9 +156,15 @@ class MenuBar(component.Component):
self.builder.get_object(widget).hide()
self.builder.get_object(widget).set_no_show_all(True)
- self.main_builder.get_object('separatormenuitem').set_visible(not self.config['standalone'])
- self.main_builder.get_object('menuitem_quitdaemon').set_visible(not self.config['standalone'])
- self.main_builder.get_object('menuitem_connectionmanager').set_visible(not self.config['standalone'])
+ self.main_builder.get_object('separatormenuitem').set_visible(
+ not self.config['standalone']
+ )
+ self.main_builder.get_object('menuitem_quitdaemon').set_visible(
+ not self.config['standalone']
+ )
+ self.main_builder.get_object('menuitem_connectionmanager').set_visible(
+ not self.config['standalone']
+ )
# Show the Torrent menu because we're connected to a host
self.menu_torrent.show()
@@ -148,21 +172,35 @@ class MenuBar(component.Component):
if client.get_auth_level() == deluge.common.AUTH_LEVEL_ADMIN:
# Get known accounts to allow changing ownership
client.core.get_known_accounts().addCallback(
- self._on_known_accounts,
+ self._on_known_accounts
).addErrback(self._on_known_accounts_fail)
- client.register_event_handler('TorrentStateChangedEvent', self.on_torrentstatechanged_event)
- client.register_event_handler('TorrentResumedEvent', self.on_torrentresumed_event)
+ client.register_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrentstatechanged_event
+ )
+ client.register_event_handler(
+ 'TorrentResumedEvent', self.on_torrentresumed_event
+ )
client.register_event_handler('SessionPausedEvent', self.on_sessionpaused_event)
- client.register_event_handler('SessionResumedEvent', self.on_sessionresumed_event)
+ client.register_event_handler(
+ 'SessionResumedEvent', self.on_sessionresumed_event
+ )
def stop(self):
log.debug('MenuBar stopping')
- client.deregister_event_handler('TorrentStateChangedEvent', self.on_torrentstatechanged_event)
- client.deregister_event_handler('TorrentResumedEvent', self.on_torrentresumed_event)
- client.deregister_event_handler('SessionPausedEvent', self.on_sessionpaused_event)
- client.deregister_event_handler('SessionResumedEvent', self.on_sessionresumed_event)
+ client.deregister_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrentstatechanged_event
+ )
+ client.deregister_event_handler(
+ 'TorrentResumedEvent', self.on_torrentresumed_event
+ )
+ client.deregister_event_handler(
+ 'SessionPausedEvent', self.on_sessionpaused_event
+ )
+ client.deregister_event_handler(
+ 'SessionResumedEvent', self.on_sessionresumed_event
+ )
for widget in self.change_sensitivity:
self.main_builder.get_object(widget).set_sensitive(False)
@@ -212,6 +250,7 @@ class MenuBar(component.Component):
def on_menuitem_createtorrent_activate(self, data=None):
log.debug('on_menuitem_createtorrent_activate')
from deluge.ui.gtkui.createtorrentdialog import CreateTorrentDialog
+
CreateTorrentDialog().show()
def on_menuitem_quitdaemon_activate(self, data=None):
@@ -234,28 +273,24 @@ class MenuBar(component.Component):
# Torrent Menu #
def on_menuitem_pause_activate(self, data=None):
log.debug('on_menuitem_pause_activate')
- client.core.pause_torrent(
- component.get('TorrentView').get_selected_torrents(),
- )
+ client.core.pause_torrent(component.get('TorrentView').get_selected_torrents())
def on_menuitem_resume_activate(self, data=None):
log.debug('on_menuitem_resume_activate')
- client.core.resume_torrent(
- component.get('TorrentView').get_selected_torrents(),
- )
+ client.core.resume_torrent(component.get('TorrentView').get_selected_torrents())
def on_menuitem_updatetracker_activate(self, data=None):
log.debug('on_menuitem_updatetracker_activate')
client.core.force_reannounce(
- component.get('TorrentView').get_selected_torrents(),
+ component.get('TorrentView').get_selected_torrents()
)
def on_menuitem_edittrackers_activate(self, data=None):
log.debug('on_menuitem_edittrackers_activate')
from deluge.ui.gtkui.edittrackersdialog import EditTrackersDialog
+
dialog = EditTrackersDialog(
- component.get('TorrentView').get_selected_torrent(),
- self.mainwindow.window,
+ component.get('TorrentView').get_selected_torrent(), self.mainwindow.window
)
dialog.run()
@@ -264,39 +299,42 @@ class MenuBar(component.Component):
torrent_ids = component.get('TorrentView').get_selected_torrents()
if torrent_ids:
from deluge.ui.gtkui.removetorrentdialog import RemoveTorrentDialog
+
RemoveTorrentDialog(torrent_ids).run()
def on_menuitem_recheck_activate(self, data=None):
log.debug('on_menuitem_recheck_activate')
- client.core.force_recheck(
- component.get('TorrentView').get_selected_torrents(),
- )
+ client.core.force_recheck(component.get('TorrentView').get_selected_torrents())
def on_menuitem_open_folder_activate(self, data=None):
log.debug('on_menuitem_open_folder')
def _on_torrent_status(status):
timestamp = gtk.get_current_event_time()
- path = os.path.join(status['download_location'], status['files'][0]['path'].split('/')[0])
+ path = os.path.join(
+ status['download_location'], status['files'][0]['path'].split('/')[0]
+ )
deluge.common.show_file(path, timestamp=timestamp)
+
for torrent_id in component.get('TorrentView').get_selected_torrents():
component.get('SessionProxy').get_torrent_status(
- torrent_id, ['download_location', 'files'],
+ torrent_id, ['download_location', 'files']
).addCallback(_on_torrent_status)
def on_menuitem_move_activate(self, data=None):
log.debug('on_menuitem_move_activate')
component.get('SessionProxy').get_torrent_status(
- component.get('TorrentView').get_selected_torrent(),
- ['download_location'],
+ component.get('TorrentView').get_selected_torrent(), ['download_location']
).addCallback(self.show_move_storage_dialog)
def show_move_storage_dialog(self, status):
log.debug('show_move_storage_dialog')
builder = gtk.Builder()
- builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'move_storage_dialog.ui'),
- ))
+ builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'move_storage_dialog.ui')
+ )
+ )
# Keep it referenced:
# https://bugzilla.gnome.org/show_bug.cgi?id=546802
self.move_storage_dialog = builder.get_object('move_storage_dialog')
@@ -319,12 +357,11 @@ class MenuBar(component.Component):
if response_id == gtk.RESPONSE_OK:
log.debug(
- 'Moving torrents to %s',
- self.move_storage_path_chooser.get_text(),
+ 'Moving torrents to %s', self.move_storage_path_chooser.get_text()
)
path = self.move_storage_path_chooser.get_text()
client.core.move_storage(
- component.get('TorrentView').get_selected_torrents(), path,
+ component.get('TorrentView').get_selected_torrents(), path
).addCallback(on_core_result)
self.move_storage_dialog.connect('response', on_dialog_response_event)
@@ -375,6 +412,7 @@ class MenuBar(component.Component):
def on_menuitem_about_activate(self, data=None):
log.debug('on_menuitem_about_activate')
from deluge.ui.gtkui.aboutdialog import AboutDialog
+
AboutDialog().run()
def on_menuitem_set_unlimited(self, widget):
@@ -401,22 +439,35 @@ class MenuBar(component.Component):
other_dialog_info = {
'menuitem_down_speed': [
- _('Download Speed Limit'), _('Set the maximum download speed'),
- _('KiB/s'), 'downloading.svg',
+ _('Download Speed Limit'),
+ _('Set the maximum download speed'),
+ _('KiB/s'),
+ 'downloading.svg',
],
'menuitem_up_speed': [
- _('Upload Speed Limit'), _('Set the maximum upload speed'),
- _('KiB/s'), 'seeding.svg',
+ _('Upload Speed Limit'),
+ _('Set the maximum upload speed'),
+ _('KiB/s'),
+ 'seeding.svg',
],
'menuitem_max_connections': [
- _('Incoming Connections'), _('Set the maximum incoming connections'),
- '', gtk.STOCK_NETWORK,
+ _('Incoming Connections'),
+ _('Set the maximum incoming connections'),
+ '',
+ gtk.STOCK_NETWORK,
],
'menuitem_upload_slots': [
- _('Peer Upload Slots'), _('Set the maximum upload slots'),
- '', gtk.STOCK_SORT_ASCENDING,
+ _('Peer Upload Slots'),
+ _('Set the maximum upload slots'),
+ '',
+ gtk.STOCK_SORT_ASCENDING,
+ ],
+ 'menuitem_stop_seed_at_ratio': [
+ _('Stop Seed At Ratio'),
+ 'Stop torrent seeding at ratio',
+ '',
+ None,
],
- 'menuitem_stop_seed_at_ratio': [_('Stop Seed At Ratio'), 'Stop torrent seeding at ratio', '', None],
}
core_key = status_map[widget.get_name()][0]
@@ -443,15 +494,16 @@ class MenuBar(component.Component):
torrent_ids = component.get('TorrentView').get_selected_torrents()
if len(torrent_ids) == 1:
core_key_global = core_key
- d = component.get('SessionProxy').get_torrent_status(torrent_ids[0], [core_key])
+ d = component.get('SessionProxy').get_torrent_status(
+ torrent_ids[0], [core_key]
+ )
else:
d = client.core.get_config_values([core_key_global])
d.addCallback(_on_torrent_status)
def on_menuitem_set_automanaged_on(self, widget):
client.core.set_torrent_options(
- component.get('TorrentView').get_selected_torrents(),
- {'auto_managed': True},
+ component.get('TorrentView').get_selected_torrents(), {'auto_managed': True}
)
def on_menuitem_set_automanaged_off(self, widget):
@@ -510,9 +562,11 @@ class MenuBar(component.Component):
self.change_owner_submenu_items[None].set_active(True)
self.change_owner_submenu_items[None].hide()
self.builder.get_object('menuitem_change_owner').connect(
- 'activate', self._on_change_owner_submenu_active,
+ 'activate', self._on_change_owner_submenu_active
+ )
+ self.builder.get_object('menuitem_change_owner').set_submenu(
+ self.change_owner_submenu
)
- self.builder.get_object('menuitem_change_owner').set_submenu(self.change_owner_submenu)
def _on_known_accounts_fail(self, reason):
self.builder.get_object('menuitem_change_owner').set_visible(False)
@@ -524,7 +578,9 @@ class MenuBar(component.Component):
self.change_owner_submenu_items[None].set_active(True)
return
- torrent_owner = component.get('TorrentView').get_torrent_status(selected[0])['owner']
+ torrent_owner = component.get('TorrentView').get_torrent_status(selected[0])[
+ 'owner'
+ ]
for username, item in self.change_owner_submenu_items.items():
item.set_active(username == torrent_owner)
@@ -544,8 +600,10 @@ class MenuBar(component.Component):
ErrorDialog(
_('Ownership Change Error'),
_('There was an error while trying changing ownership.'),
- self.mainwindow.window, details=failure.value.logable(),
+ self.mainwindow.window,
+ details=failure.value.logable(),
).run()
+
client.core.set_torrent_options(
- update_torrents, {'owner': username},
+ update_torrents, {'owner': username}
).addErrback(failed_change_owner)
diff --git a/deluge/ui/gtkui/menubar_osx.py b/deluge/ui/gtkui/menubar_osx.py
index 64cfbbad7..511594b04 100644
--- a/deluge/ui/gtkui/menubar_osx.py
+++ b/deluge/ui/gtkui/menubar_osx.py
@@ -41,7 +41,14 @@ def menubar_osx(gtkui, osxapp):
accel_meta(file_items[0], group, 'o')
accel_meta(file_items[1], group, 'n')
quit_all_item = file_items[3]
- accel_swap(quit_all_item, group, 'q', SHIFT_MASK | CONTROL_MASK, 'q', SHIFT_MASK | META_MASK)
+ accel_swap(
+ quit_all_item,
+ group,
+ 'q',
+ SHIFT_MASK | CONTROL_MASK,
+ 'q',
+ SHIFT_MASK | META_MASK,
+ )
for item in range(2, len(file_items)): # remove quits
file_menu.remove(file_items[item])
diff --git a/deluge/ui/gtkui/new_release_dialog.py b/deluge/ui/gtkui/new_release_dialog.py
index c9df8a5bc..246fc0ec8 100644
--- a/deluge/ui/gtkui/new_release_dialog.py
+++ b/deluge/ui/gtkui/new_release_dialog.py
@@ -16,7 +16,6 @@ from deluge.ui.client import client
class NewReleaseDialog(object):
-
def __init__(self):
pass
@@ -27,30 +26,35 @@ class NewReleaseDialog(object):
# Set the version labels
if deluge.common.windows_check() or deluge.common.osx_check():
main_builder.get_object('image_new_release').set_from_file(
- deluge.common.get_pixmap('deluge16.png'),
+ deluge.common.get_pixmap('deluge16.png')
)
else:
main_builder.get_object('image_new_release').set_from_icon_name('deluge', 4)
main_builder.get_object('label_available_version').set_text(available_version)
main_builder.get_object('label_client_version').set_text(
- deluge.common.get_version(),
+ deluge.common.get_version()
+ )
+ self.chk_not_show_dialog = main_builder.get_object(
+ 'chk_do_not_show_new_release'
)
- self.chk_not_show_dialog = main_builder.get_object('chk_do_not_show_new_release')
main_builder.get_object('button_goto_downloads').connect(
- 'clicked', self._on_button_goto_downloads,
+ 'clicked', self._on_button_goto_downloads
)
main_builder.get_object('button_close_new_release').connect(
- 'clicked', self._on_button_close_new_release,
+ 'clicked', self._on_button_close_new_release
)
if client.connected():
+
def on_info(version):
main_builder.get_object('label_server_version').set_text(version)
main_builder.get_object('label_server_version').show()
main_builder.get_object('label_server_version_text').show()
if not client.is_standalone():
- main_builder.get_object('label_client_version_text').set_label(_('<i>Client Version</i>'))
+ main_builder.get_object('label_client_version_text').set_label(
+ _('<i>Client Version</i>')
+ )
client.daemon.info().addCallback(on_info)
self.dialog.show()
diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py
index 6fdb13d2e..7e4199ba7 100644
--- a/deluge/ui/gtkui/options_tab.py
+++ b/deluge/ui/gtkui/options_tab.py
@@ -30,9 +30,15 @@ class OptionsTab(Tab):
self.add_tab_widget('spin_max_download', 'value', ['max_download_speed'])
self.add_tab_widget('spin_max_upload', 'value', ['max_upload_speed'])
self.add_tab_widget('spin_max_connections', 'value_as_int', ['max_connections'])
- self.add_tab_widget('spin_max_upload_slots', 'value_as_int', ['max_upload_slots'])
- self.add_tab_widget('chk_prioritize_first_last', 'active', ['prioritize_first_last_pieces'])
- self.add_tab_widget('chk_sequential_download', 'active', ['sequential_download'])
+ self.add_tab_widget(
+ 'spin_max_upload_slots', 'value_as_int', ['max_upload_slots']
+ )
+ self.add_tab_widget(
+ 'chk_prioritize_first_last', 'active', ['prioritize_first_last_pieces']
+ )
+ self.add_tab_widget(
+ 'chk_sequential_download', 'active', ['sequential_download']
+ )
self.add_tab_widget('chk_auto_managed', 'active', ['is_auto_managed'])
self.add_tab_widget('chk_stop_at_ratio', 'active', ['stop_at_ratio'])
self.add_tab_widget('chk_remove_at_ratio', 'active', ['remove_at_ratio'])
@@ -44,20 +50,24 @@ class OptionsTab(Tab):
# Connect key press event for spin widgets.
for widget_id in self.tab_widgets:
if widget_id.startswith('spin_'):
- self.tab_widgets[widget_id].obj.connect('key-press-event', self.on_key_press_event)
+ self.tab_widgets[widget_id].obj.connect(
+ 'key-press-event', self.on_key_press_event
+ )
self.button_apply = self.main_builder.get_object('button_apply')
self.move_completed_path_chooser = PathChooser('move_completed_paths_list')
self.move_completed_path_chooser.set_sensitive(
- self.tab_widgets['chk_move_completed'].obj.get_active(),
+ self.tab_widgets['chk_move_completed'].obj.get_active()
)
self.move_completed_path_chooser.connect(
- 'text-changed', self.on_path_chooser_text_changed_event,
+ 'text-changed', self.on_path_chooser_text_changed_event
)
self.status_keys.append('move_completed_path')
- self.move_completed_hbox = self.main_builder.get_object('hbox_move_completed_path_chooser')
+ self.move_completed_hbox = self.main_builder.get_object(
+ 'hbox_move_completed_path_chooser'
+ )
self.move_completed_hbox.add(self.move_completed_path_chooser)
self.move_completed_hbox.show_all()
@@ -85,7 +95,7 @@ class OptionsTab(Tab):
self.clear()
component.get('SessionProxy').get_torrents_status(
- {'id': torrent_ids}, self.status_keys,
+ {'id': torrent_ids}, self.status_keys
).addCallback(self.parse_torrents_statuses)
self.prev_torrent_ids = torrent_ids
@@ -137,21 +147,32 @@ class OptionsTab(Tab):
set_func = 'set_' + widget.func.replace('_as_int', '')
getattr(widget.obj, set_func)(status_value)
if set_func == 'set_active':
- widget.obj.set_inconsistent(status_key in self.inconsistent_keys)
+ widget.obj.set_inconsistent(
+ status_key in self.inconsistent_keys
+ )
- if new_status['move_completed_path'] != self.prev_status['move_completed_path']:
+ if (
+ new_status['move_completed_path']
+ != self.prev_status['move_completed_path']
+ ):
text = new_status['move_completed_path']
- self.move_completed_path_chooser.set_text(text, cursor_end=False, default_text=True)
+ self.move_completed_path_chooser.set_text(
+ text, cursor_end=False, default_text=True
+ )
# Update sensitivity of widgets.
- self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(new_status['stop_at_ratio'])
- self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(new_status['stop_at_ratio'])
+ self.tab_widgets['spin_stop_ratio'].obj.set_sensitive(
+ new_status['stop_at_ratio']
+ )
+ self.tab_widgets['chk_remove_at_ratio'].obj.set_sensitive(
+ new_status['stop_at_ratio']
+ )
# Ensure apply button sensitivity is set False.
self.button_apply.set_sensitive(False)
self.prev_status = new_status
-# === Widget signal handlers === #
+ # === Widget signal handlers === #
def on_button_apply_clicked(self, button):
options = {}
@@ -161,7 +182,8 @@ class OptionsTab(Tab):
continue # A label so read-only
widget_value = getattr(widget.obj, 'get_' + widget.func)()
if widget_value != self.prev_status[status_key] or (
- status_key in self.inconsistent_keys and not widget.obj.get_inconsistent()
+ status_key in self.inconsistent_keys
+ and not widget.obj.get_inconsistent()
):
options[status_key] = widget_value
diff --git a/deluge/ui/gtkui/path_chooser.py b/deluge/ui/gtkui/path_chooser.py
index 249b4c894..7bf081de0 100644
--- a/deluge/ui/gtkui/path_chooser.py
+++ b/deluge/ui/gtkui/path_chooser.py
@@ -25,12 +25,12 @@ def singleton(cls):
if cls not in instances:
instances[cls] = cls()
return instances[cls]
+
return getinstance
@singleton
class PathChoosersHandler(component.Component):
-
def __init__(self, paths_config_key=None):
# self.chooser_name = "PathChooser_%d" % (len(PathChooser.path_choosers) +1)
component.Component.__init__(self, 'PathChoosersHandler')
@@ -60,6 +60,7 @@ class PathChoosersHandler(component.Component):
self.config_properties.update(config)
for chooser in self.path_choosers:
chooser.set_config(config)
+
keys = list(self.config_keys_to_funcs_mapping)
keys += self.paths_list_keys
client.core.get_config_values(keys).addCallback(_on_config_values)
@@ -68,8 +69,12 @@ class PathChoosersHandler(component.Component):
chooser.config_key_funcs = {}
for key in self.config_keys_to_funcs_mapping:
chooser.config_key_funcs[key] = [None, None]
- chooser.config_key_funcs[key][0] = getattr(chooser, 'get_%s' % self.config_keys_to_funcs_mapping[key])
- chooser.config_key_funcs[key][1] = getattr(chooser, 'set_%s' % self.config_keys_to_funcs_mapping[key])
+ chooser.config_key_funcs[key][0] = getattr(
+ chooser, 'get_%s' % self.config_keys_to_funcs_mapping[key]
+ )
+ chooser.config_key_funcs[key][1] = getattr(
+ chooser, 'set_%s' % self.config_keys_to_funcs_mapping[key]
+ )
self.path_choosers.append(chooser)
if chooser.paths_config_key not in self.paths_list_keys:
@@ -95,7 +100,9 @@ class PathChoosersHandler(component.Component):
# The value hasn't been changed in one second, so save to core
if self.max_rows_value_set == value_:
client.core.set_config({'path_chooser_max_popup_rows': value})
+
from twisted.internet import reactor
+
reactor.callLater(1, update, value)
def on_list_values_changed(self, values, key, caller):
@@ -115,7 +122,6 @@ class PathChoosersHandler(component.Component):
class PathChooser(PathChooserComboBox):
-
def __init__(self, paths_config_key=None):
self.paths_config_key = paths_config_key
super(PathChooser, self).__init__()
@@ -123,34 +129,52 @@ class PathChooser(PathChooserComboBox):
self.chooser_handler.register_chooser(self)
self.set_auto_completer_func(self.on_completion)
self.connect('list-values-changed', self.on_list_values_changed_event)
- self.connect('auto-complete-enabled-toggled', self.on_auto_complete_enabled_toggled)
+ self.connect(
+ 'auto-complete-enabled-toggled', self.on_auto_complete_enabled_toggled
+ )
self.connect('show-filechooser-toggled', self.on_show_filechooser_toggled)
- self.connect('show-folder-name-on-button', self.on_show_folder_on_button_toggled)
+ self.connect(
+ 'show-folder-name-on-button', self.on_show_folder_on_button_toggled
+ )
self.connect('show-path-entry-toggled', self.on_show_path_entry_toggled)
self.connect('accelerator-set', self.on_accelerator_set)
self.connect('max-rows-changed', self.on_max_rows_changed)
self.connect('show-hidden-files-toggled', self.on_show_hidden_files_toggled)
def on_auto_complete_enabled_toggled(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_auto_complete_enabled')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_auto_complete_enabled'
+ )
def on_show_filechooser_toggled(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_show_chooser_button_on_localhost')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_show_chooser_button_on_localhost'
+ )
def on_show_folder_on_button_toggled(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_show_folder_name')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_show_folder_name'
+ )
def on_show_path_entry_toggled(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_show_path_entry')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_show_path_entry'
+ )
def on_accelerator_set(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_accelerator_string')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_accelerator_string'
+ )
def on_show_hidden_files_toggled(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_show_hidden_files')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_show_hidden_files'
+ )
def on_max_rows_changed(self, widget, value):
- self.chooser_handler.set_value_for_path_choosers(value, 'path_chooser_max_popup_rows')
+ self.chooser_handler.set_value_for_path_choosers(
+ value, 'path_chooser_max_popup_rows'
+ )
def on_list_values_changed_event(self, widget, values):
self.chooser_handler.on_list_values_changed(values, self.paths_config_key, self)
@@ -171,5 +195,6 @@ class PathChooser(PathChooserComboBox):
def on_completion(self, args):
def on_paths_cb(args):
self.complete(args)
+
d = client.core.get_completion_paths(args)
d.addCallback(on_paths_cb)
diff --git a/deluge/ui/gtkui/path_combo_chooser.py b/deluge/ui/gtkui/path_combo_chooser.py
index f45335623..7d5c46ffd 100755
--- a/deluge/ui/gtkui/path_combo_chooser.py
+++ b/deluge/ui/gtkui/path_combo_chooser.py
@@ -77,8 +77,7 @@ class ValueList(object):
return values
def add_values(
- self, paths, append=True, scroll_to_row=False,
- clear=False, emit_signal=False,
+ self, paths, append=True, scroll_to_row=False, clear=False, emit_signal=False
):
"""
Add paths to the liststore
@@ -155,7 +154,7 @@ class ValueList(object):
if index == len(self.tree_store):
index -= 1
if index >= 0:
- path = (index, )
+ path = (index,)
self.treeview.set_cursor(path)
self.set_path_selected(path)
self.emit('list-value-removed', path_value)
@@ -194,11 +193,9 @@ class ValueList(object):
keyval = event.keyval
state = event.get_state() & gtk.accelerator_get_default_mod_mask()
- if keyval == keysyms.Escape or\
- (
- key_is_up(keyval) and
- state == gdk.MOD1_MASK
- ): # ALT Key
+ if keyval == keysyms.Escape or (
+ key_is_up(keyval) and state == gdk.MOD1_MASK
+ ): # ALT Key
self.popdown()
return True
# Set entry value to the selected row
@@ -219,15 +216,18 @@ class ValueList(object):
if event.button != 3:
# Double clicked a row, set this as the entry value
# and close the popup
- if (double_click and event.type == gdk._2BUTTON_PRESS) or\
- (not double_click and event.type == gdk.BUTTON_PRESS):
+ if (double_click and event.type == gdk._2BUTTON_PRESS) or (
+ not double_click and event.type == gdk.BUTTON_PRESS
+ ):
path = self.get_selection_path()
if path:
self.set_entry_value(path, popdown=True)
return True
return False
- def handle_list_scroll(self, _next=None, path=None, set_entry=False, swap=False, scroll_window=False):
+ def handle_list_scroll(
+ self, _next=None, path=None, set_entry=False, swap=False, scroll_window=False
+ ):
"""
Handles changes to the row selection.
@@ -279,7 +279,7 @@ class ValueList(object):
return
# This is a regular scroll, not setting value in entry or swapping rows,
# so we find a path value anyways
- path = (0, )
+ path = (0,)
cursor = self.treeview.get_cursor()
if cursor is not None and cursor[0] is not None:
path = cursor[0]
@@ -299,13 +299,12 @@ class ValueList(object):
index = len(self.tree_store) - 1
# We have the index for the new path
- new_path = (index)
+ new_path = index
if swap:
p1 = self.tree_store[path][0]
p2 = self.tree_store[new_path][0]
self.tree_store.swap(
- self.tree_store.get_iter(path),
- self.tree_store.get_iter(new_path),
+ self.tree_store.get_iter(path), self.tree_store.get_iter(new_path)
)
self.emit('list-values-reordered', [p1, p2])
self.emit('list-values-changed', self.get_values())
@@ -318,7 +317,6 @@ class ValueList(object):
class StoredValuesList(ValueList):
-
def __init__(self):
self.tree_store = self.builder.get_object('stored_values_tree_store')
self.tree_column = self.builder.get_object('stored_values_treeview_column')
@@ -326,15 +324,20 @@ class StoredValuesList(ValueList):
self.paths_without_trailing_path_sep = False
# Add signal handlers
- self.signal_handlers['on_stored_values_treeview_mouse_button_press_event'] = \
- self.on_treeview_mouse_button_press_event
+ self.signal_handlers[
+ 'on_stored_values_treeview_mouse_button_press_event'
+ ] = self.on_treeview_mouse_button_press_event
- self.signal_handlers['on_stored_values_treeview_key_press_event'] = \
- self.on_stored_values_treeview_key_press_event
- self.signal_handlers['on_stored_values_treeview_key_release_event'] = \
- self.on_stored_values_treeview_key_release_event
+ self.signal_handlers[
+ 'on_stored_values_treeview_key_press_event'
+ ] = self.on_stored_values_treeview_key_press_event
+ self.signal_handlers[
+ 'on_stored_values_treeview_key_release_event'
+ ] = self.on_stored_values_treeview_key_release_event
- self.signal_handlers['on_cellrenderertext_edited'] = self.on_cellrenderertext_edited
+ self.signal_handlers[
+ 'on_cellrenderertext_edited'
+ ] = self.on_cellrenderertext_edited
def on_cellrenderertext_edited(self, cellrenderertext, path, new_text):
"""
@@ -369,7 +372,9 @@ class StoredValuesList(ValueList):
"""
# This is left click
if event.button != 3:
- super(StoredValuesList, self).on_treeview_mouse_button_press_event(treeview, event, double_click=True)
+ super(StoredValuesList, self).on_treeview_mouse_button_press_event(
+ treeview, event, double_click=True
+ )
return False
# This is right click, create popup menu for this row
@@ -405,7 +410,9 @@ class StoredValuesList(ValueList):
PathChooserPopup.popup(self)
def on_stored_values_treeview_key_press_event(self, widget, event):
- super(StoredValuesList, self).on_value_list_treeview_key_press_event(widget, event)
+ super(StoredValuesList, self).on_value_list_treeview_key_press_event(
+ widget, event
+ )
# Prevent the default event handler to move the cursor in the list
if key_is_up_or_down(event.keyval):
return True
@@ -422,17 +429,14 @@ class StoredValuesList(ValueList):
ctrl = event.get_state() & gdk.CONTROL_MASK
# Edit selected row
- if (keyval in [keysyms.Left, keysyms.Right, keysyms.space]):
+ if keyval in [keysyms.Left, keysyms.Right, keysyms.space]:
path = self.get_selection_path()
if path:
self.on_edit_path(path, self.tree_column)
elif key_is_up_or_down(keyval):
# Swap the row value
if event.get_state() & gdk.CONTROL_MASK:
- self.handle_list_scroll(
- _next=key_is_down(keyval),
- swap=True,
- )
+ self.handle_list_scroll(_next=key_is_down(keyval), swap=True)
else:
self.handle_list_scroll(_next=key_is_down(keyval))
elif key_is_pgup_or_pgdown(event.keyval):
@@ -447,7 +451,9 @@ class StoredValuesList(ValueList):
return True
# Add current value to saved list
elif is_ascii_value(keyval, 's'):
- super(PathChooserComboBox, self).add_current_value_to_saved_list() # pylint: disable=bad-super-call
+ super(
+ PathChooserComboBox, self
+ ).add_current_value_to_saved_list() # pylint: disable=bad-super-call
return True
# Edit selected value
elif is_ascii_value(keyval, 'e'):
@@ -456,20 +462,24 @@ class StoredValuesList(ValueList):
class CompletionList(ValueList):
-
def __init__(self):
self.tree_store = self.builder.get_object('completion_tree_store')
self.tree_column = self.builder.get_object('completion_treeview_column')
self.rendererText = self.builder.get_object('completion_cellrenderertext')
- self.completion_scrolled_window = self.builder.get_object('completion_scrolled_window')
- self.signal_handlers['on_completion_treeview_key_press_event'] = \
- self.on_completion_treeview_key_press_event
- self.signal_handlers['on_completion_treeview_motion_notify_event'] = \
- self.on_completion_treeview_motion_notify_event
+ self.completion_scrolled_window = self.builder.get_object(
+ 'completion_scrolled_window'
+ )
+ self.signal_handlers[
+ 'on_completion_treeview_key_press_event'
+ ] = self.on_completion_treeview_key_press_event
+ self.signal_handlers[
+ 'on_completion_treeview_motion_notify_event'
+ ] = self.on_completion_treeview_motion_notify_event
# Add super class signal handler
- self.signal_handlers['on_completion_treeview_mouse_button_press_event'] = \
- super(CompletionList, self).on_treeview_mouse_button_press_event
+ self.signal_handlers['on_completion_treeview_mouse_button_press_event'] = super(
+ CompletionList, self
+ ).on_treeview_mouse_button_press_event
def reduce_values(self, prefix):
"""
@@ -487,7 +497,9 @@ class CompletionList(ValueList):
self.add_values(matching_values, clear=True)
def on_completion_treeview_key_press_event(self, widget, event):
- ret = super(CompletionList, self).on_value_list_treeview_key_press_event(widget, event)
+ ret = super(CompletionList, self).on_value_list_treeview_key_press_event(
+ widget, event
+ )
if ret:
return ret
keyval = event.keyval
@@ -498,7 +510,9 @@ class CompletionList(ValueList):
elif ctrl:
# Set show/hide hidden files
if is_ascii_value(keyval, 'h'):
- self.path_entry.set_show_hidden_files(not self.path_entry.get_show_hidden_files(), do_completion=True)
+ self.path_entry.set_show_hidden_files(
+ not self.path_entry.get_show_hidden_files(), do_completion=True
+ )
return True
def on_completion_treeview_motion_notify_event(self, widget, event):
@@ -515,13 +529,16 @@ class CompletionList(ValueList):
class PathChooserPopup(object):
"""This creates the popop window for the ComboEntry."""
+
def __init__(self, min_visible_rows, max_visible_rows, popup_alignment_widget):
self.min_visible_rows = min_visible_rows
# Maximum number of rows to display without scrolling
self.set_max_popup_rows(max_visible_rows)
self.popup_window.realize()
self.alignment_widget = popup_alignment_widget
- self.popup_buttonbox = None # If set, the height of this widget is the minimum height
+ self.popup_buttonbox = (
+ None
+ ) # If set, the height of this widget is the minimum height
def popup(self):
"""Make the popup visible."""
@@ -579,8 +596,14 @@ class PathChooserPopup(object):
width = self.popup_window.size_request()[0]
if self.popup_buttonbox:
- buttonbox_height = max(self.popup_buttonbox.size_request()[1], self.popup_buttonbox.get_allocation().height)
- buttonbox_width = max(self.popup_buttonbox.size_request()[0], self.popup_buttonbox.get_allocation().width)
+ buttonbox_height = max(
+ self.popup_buttonbox.size_request()[1],
+ self.popup_buttonbox.get_allocation().height,
+ )
+ buttonbox_width = max(
+ self.popup_buttonbox.size_request()[0],
+ self.popup_buttonbox.get_allocation().width,
+ )
treeview_width = self.treeview.size_request()[0]
# After removing an element from the tree store, self.treeview.size_request()[0]
# returns -1 for some reason, so the requested width cannot be used until the treeview
@@ -631,14 +654,17 @@ class PathChooserPopup(object):
x = monitor.x + monitor.width - width
# Set the position
- if y + self.path_entry.get_allocation().height + height <= monitor.y + monitor.height:
+ if (
+ y + self.path_entry.get_allocation().height + height
+ <= monitor.y + monitor.height
+ ):
y += self.path_entry.get_allocation().height
# Not enough space downwards on the screen
elif y - height >= monitor.y:
y -= height
elif (
- monitor.y + monitor.height - (y + self.path_entry.get_allocation().height) >
- y - monitor.y
+ monitor.y + monitor.height - (y + self.path_entry.get_allocation().height)
+ > y - monitor.y
):
y += self.path_entry.get_allocation().height
height = monitor.y + monitor.height - y
@@ -650,19 +676,30 @@ class PathChooserPopup(object):
def popup_grab_window(self):
activate_time = 0
- if gdk.pointer_grab(
- self.popup_window.get_window(), True,
- (
- gdk.BUTTON_PRESS_MASK |
- gdk.BUTTON_RELEASE_MASK |
- gdk.POINTER_MOTION_MASK
- ),
- None, None, activate_time,
- ) == 0:
- if gdk.keyboard_grab(self.popup_window.get_window(), True, activate_time) == 0:
+ if (
+ gdk.pointer_grab(
+ self.popup_window.get_window(),
+ True,
+ (
+ gdk.BUTTON_PRESS_MASK
+ | gdk.BUTTON_RELEASE_MASK
+ | gdk.POINTER_MOTION_MASK
+ ),
+ None,
+ None,
+ activate_time,
+ )
+ == 0
+ ):
+ if (
+ gdk.keyboard_grab(self.popup_window.get_window(), True, activate_time)
+ == 0
+ ):
return True
else:
- self.popup_window.get_window().get_display().pointer_ungrab(activate_time)
+ self.popup_window.get_window().get_display().pointer_ungrab(
+ activate_time
+ )
return False
return False
@@ -671,7 +708,9 @@ class PathChooserPopup(object):
Sets the text of the entry to the value in path
"""
- self.path_entry.set_text(self.tree_store[path][0], set_file_chooser_folder=True, trigger_event=True)
+ self.path_entry.set_text(
+ self.tree_store[path][0], set_file_chooser_folder=True, trigger_event=True
+ )
if popdown:
self.popdown()
@@ -686,21 +725,20 @@ class PathChooserPopup(object):
def get_max_popup_rows(self):
return self.max_visible_rows
-#################
-# Callbacks
-#################
+ #################
+ # Callbacks
+ #################
def on_popup_window_button_press_event(self, window, event):
# If we're clicking outside of the window close the popup
hide = False
# Also if the intersection of self and the event is empty, hide
# the path_list
- if (tuple(self.popup_window.get_allocation().intersect(
- gdk.Rectangle(
- x=int(event.x), y=int(event.y),
- width=1, height=1,
- ),
- )) == (0, 0, 0, 0)):
+ if tuple(
+ self.popup_window.get_allocation().intersect(
+ gdk.Rectangle(x=int(event.x), y=int(event.y), width=1, height=1)
+ )
+ ) == (0, 0, 0, 0):
hide = True
# Toplevel is the window that received the event, and parent is the
# path_list window. If they are not the same, means the popup should
@@ -721,6 +759,7 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
The stored values popup
"""
+
def __init__(self, builder, path_entry, max_visible_rows, popup_alignment_widget):
self.builder = builder
self.treeview = self.builder.get_object('stored_values_treeview')
@@ -736,15 +775,23 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
self.popup_buttonbox = self.builder.get_object('buttonbox')
# Add signal handlers
- self.signal_handlers['on_buttonbox_key_press_event'] = self.on_buttonbox_key_press_event
- self.signal_handlers['on_stored_values_treeview_scroll_event'] = self.on_scroll_event
- self.signal_handlers['on_button_toggle_dropdown_scroll_event'] = self.on_scroll_event
+ self.signal_handlers[
+ 'on_buttonbox_key_press_event'
+ ] = self.on_buttonbox_key_press_event
+ self.signal_handlers[
+ 'on_stored_values_treeview_scroll_event'
+ ] = self.on_scroll_event
+ self.signal_handlers[
+ 'on_button_toggle_dropdown_scroll_event'
+ ] = self.on_scroll_event
self.signal_handlers['on_entry_text_scroll_event'] = self.on_scroll_event
- self.signal_handlers['on_stored_values_popup_window_focus_out_event'] = \
- self.on_stored_values_popup_window_focus_out_event
+ self.signal_handlers[
+ 'on_stored_values_popup_window_focus_out_event'
+ ] = self.on_stored_values_popup_window_focus_out_event
# For when clicking outside the popup
- self.signal_handlers['on_stored_values_popup_window_button_press_event'] = \
- self.on_popup_window_button_press_event
+ self.signal_handlers[
+ 'on_stored_values_popup_window_button_press_event'
+ ] = self.on_popup_window_button_press_event
# Buttons for manipulating the list
self.signal_handlers['on_button_add_clicked'] = self.on_button_add_clicked
@@ -752,8 +799,12 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
self.signal_handlers['on_button_remove_clicked'] = self.on_button_remove_clicked
self.signal_handlers['on_button_up_clicked'] = self.on_button_up_clicked
self.signal_handlers['on_button_down_clicked'] = self.on_button_down_clicked
- self.signal_handlers['on_button_default_clicked'] = self.on_button_default_clicked
- self.signal_handlers['on_button_properties_clicked'] = self.path_entry._on_button_properties_clicked
+ self.signal_handlers[
+ 'on_button_default_clicked'
+ ] = self.on_button_default_clicked
+ self.signal_handlers[
+ 'on_button_properties_clicked'
+ ] = self.path_entry._on_button_properties_clicked
def popup(self):
"""
@@ -772,11 +823,13 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
self.popup_window.grab_add()
# Set value selected if it exists
- self.set_selected_value(path_without_trailing_path_sep(self.path_entry.get_text()))
+ self.set_selected_value(
+ path_without_trailing_path_sep(self.path_entry.get_text())
+ )
-#################
-# Callbacks
-#################
+ #################
+ # Callbacks
+ #################
def on_stored_values_popup_window_focus_out_event(self, entry, event):
"""
@@ -795,7 +848,9 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
scroll_window = event.get_state() & gdk.SHIFT_MASK
self.handle_list_scroll(
_next=event.direction == gdk.SCROLL_DOWN,
- set_entry=widget != self.treeview, swap=swap, scroll_window=scroll_window,
+ set_entry=widget != self.treeview,
+ swap=swap,
+ scroll_window=scroll_window,
)
return True
@@ -811,9 +866,9 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
return True
return False
-# --------------------------------------------------
-# Funcs and callbacks on the buttons to manipulate the list
-# --------------------------------------------------
+ # --------------------------------------------------
+ # Funcs and callbacks on the buttons to manipulate the list
+ # --------------------------------------------------
def add_current_value_to_saved_list(self):
text = self.path_entry.get_text()
text = path_without_trailing_path_sep(text)
@@ -858,6 +913,7 @@ class PathCompletionPopup(CompletionList, PathChooserPopup):
The auto completion popup
"""
+
def __init__(self, builder, path_entry, max_visible_rows):
self.builder = builder
self.treeview = self.builder.get_object('completion_treeview')
@@ -871,13 +927,17 @@ class PathCompletionPopup(CompletionList, PathChooserPopup):
CompletionList.__init__(self)
# Add signal handlers
- self.signal_handlers['on_completion_treeview_scroll_event'] = self.on_scroll_event
- self.signal_handlers['on_completion_popup_window_focus_out_event'] = \
- self.on_completion_popup_window_focus_out_event
+ self.signal_handlers[
+ 'on_completion_treeview_scroll_event'
+ ] = self.on_scroll_event
+ self.signal_handlers[
+ 'on_completion_popup_window_focus_out_event'
+ ] = self.on_completion_popup_window_focus_out_event
# For when clicking outside the popup
- self.signal_handlers['on_completion_popup_window_button_press_event'] = \
- self.on_popup_window_button_press_event
+ self.signal_handlers[
+ 'on_completion_popup_window_button_press_event'
+ ] = self.on_popup_window_button_press_event
def popup(self):
"""
@@ -897,11 +957,14 @@ class PathCompletionPopup(CompletionList, PathChooserPopup):
self.popup_window.grab_add()
self.text_entry.grab_focus()
self.text_entry.set_position(len(self.path_entry.text_entry.get_text()))
- self.set_selected_value(path_without_trailing_path_sep(self.path_entry.get_text()), select_first=True)
+ self.set_selected_value(
+ path_without_trailing_path_sep(self.path_entry.get_text()),
+ select_first=True,
+ )
-#################
-# Callbacks
-#################
+ #################
+ # Callbacks
+ #################
def on_completion_popup_window_focus_out_event(self, entry, event):
"""
@@ -919,7 +982,8 @@ class PathCompletionPopup(CompletionList, PathChooserPopup):
x, y, state = event.window.get_pointer()
self.handle_list_scroll(
_next=event.direction == gdk.SCROLL_DOWN,
- set_entry=widget != self.treeview, scroll_window=True,
+ set_entry=widget != self.treeview,
+ scroll_window=True,
)
path = self.treeview.get_path_at_pos(int(x), int(y))
if path:
@@ -928,19 +992,25 @@ class PathCompletionPopup(CompletionList, PathChooserPopup):
class PathAutoCompleter(object):
-
def __init__(self, builder, path_entry, max_visible_rows):
- self.completion_popup = PathCompletionPopup(builder, path_entry, max_visible_rows)
+ self.completion_popup = PathCompletionPopup(
+ builder, path_entry, max_visible_rows
+ )
self.path_entry = path_entry
self.dirs_cache = {}
self.use_popup = False
self.auto_complete_enabled = True
self.signal_handlers = self.completion_popup.signal_handlers
- self.signal_handlers['on_completion_popup_window_key_press_event'] = \
- self.on_completion_popup_window_key_press_event
- self.signal_handlers['on_entry_text_delete_text'] = self.on_entry_text_delete_text
- self.signal_handlers['on_entry_text_insert_text'] = self.on_entry_text_insert_text
+ self.signal_handlers[
+ 'on_completion_popup_window_key_press_event'
+ ] = self.on_completion_popup_window_key_press_event
+ self.signal_handlers[
+ 'on_entry_text_delete_text'
+ ] = self.on_entry_text_delete_text
+ self.signal_handlers[
+ 'on_entry_text_insert_text'
+ ] = self.on_entry_text_insert_text
self.accelerator_string = gtk.accelerator_name(keysyms.Tab, 0)
def on_entry_text_insert_text(self, entry, new_text, new_text_length, position):
@@ -950,7 +1020,9 @@ class PathAutoCompleter(object):
new_complete_text = cur_text[:pos] + new_text + cur_text[pos:]
# Remove all values from the list that do not start with new_complete_text
self.completion_popup.reduce_values(new_complete_text)
- self.completion_popup.set_selected_value(new_complete_text, select_first=True)
+ self.completion_popup.set_selected_value(
+ new_complete_text, select_first=True
+ )
if self.completion_popup.is_popped_up():
self.completion_popup.set_window_position_and_size()
@@ -977,8 +1049,10 @@ class PathAutoCompleter(object):
return ret
keyval = event.keyval
state = event.get_state() & gtk.accelerator_get_default_mod_mask()
- if self.is_auto_completion_accelerator(keyval, state)\
- and self.auto_complete_enabled:
+ if (
+ self.is_auto_completion_accelerator(keyval, state)
+ and self.auto_complete_enabled
+ ):
values_count = self.completion_popup.get_values_count()
if values_count == 1:
self.do_completion()
@@ -1011,7 +1085,9 @@ class PathAutoCompleter(object):
if args['forward_completion']:
common_prefix = os.path.commonprefix(paths)
if len(common_prefix) > len(value):
- self.path_entry.set_text(common_prefix, set_file_chooser_folder=True, trigger_event=True)
+ self.path_entry.set_text(
+ common_prefix, set_file_chooser_folder=True, trigger_event=True
+ )
self.path_entry.text_entry.set_position(len(self.path_entry.get_text()))
self.completion_popup.set_values(paths, preserve_selection=True)
@@ -1025,21 +1101,23 @@ class PathAutoCompleter(object):
class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
__gsignals__ = {
- b'list-value-added': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'list-value-removed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'list-values-reordered': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'list-values-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'auto-complete-enabled-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'show-filechooser-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'show-path-entry-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'show-folder-name-on-button': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'show-hidden-files-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'accelerator-set': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'max-rows-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
- b'text-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object, )),
+ b'list-value-added': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'list-value-removed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'list-values-reordered': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'list-values-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'auto-complete-enabled-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'show-filechooser-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'show-path-entry-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'show-folder-name-on-button': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'show-hidden-files-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'accelerator-set': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'max-rows-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
+ b'text-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)),
}
- def __init__(self, max_visible_rows=20, auto_complete=True, use_completer_popup=True):
+ def __init__(
+ self, max_visible_rows=20, auto_complete=True, use_completer_popup=True
+ ):
gtk.HBox.__init__(self)
GObject.__init__(self)
self._stored_values_popping_down = False
@@ -1051,12 +1129,16 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
self.setting_accelerator_key = False
self.builder = gtk.Builder()
self.popup_buttonbox = self.builder.get_object('buttonbox')
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'path_combo_chooser.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'path_combo_chooser.ui')
+ )
+ )
self.button_toggle = self.builder.get_object('button_toggle_dropdown')
self.text_entry = self.builder.get_object('entry_text')
- self.open_filechooser_dialog_button = self.builder.get_object('button_open_dialog')
+ self.open_filechooser_dialog_button = self.builder.get_object(
+ 'button_open_dialog'
+ )
self.filechooser_button = self.open_filechooser_dialog_button
self.filechooserdialog = self.builder.get_object('filechooserdialog')
self.filechooserdialog.set_transient_for(component.get('MainWindow').window)
@@ -1066,7 +1148,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
self.combo_hbox = self.builder.get_object('entry_combobox_hbox')
# Change the parent of the hbox from the glade Window to this hbox.
self.combo_hbox.reparent(self)
- StoredValuesPopup.__init__(self, self.builder, self, max_visible_rows, self.combo_hbox)
+ StoredValuesPopup.__init__(
+ self, self.builder, self, max_visible_rows, self.combo_hbox
+ )
self.auto_completer = PathAutoCompleter(self.builder, self, max_visible_rows)
self.auto_completer.set_use_popup(use_completer_popup)
@@ -1094,16 +1178,27 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
"""
return self.text_entry.get_text()
- def set_text(self, text, set_file_chooser_folder=True, cursor_end=True, default_text=False, trigger_event=False):
+ def set_text(
+ self,
+ text,
+ set_file_chooser_folder=True,
+ cursor_end=True,
+ default_text=False,
+ trigger_event=False,
+ ):
"""
Set the text for the entry.
"""
old_text = self.text_entry.get_text()
# We must block the "delete-text" signal to avoid the signal handler being called
- self.text_entry.handler_block_by_func(self.auto_completer.on_entry_text_delete_text)
+ self.text_entry.handler_block_by_func(
+ self.auto_completer.on_entry_text_delete_text
+ )
self.text_entry.set_text(text)
- self.text_entry.handler_unblock_by_func(self.auto_completer.on_entry_text_delete_text)
+ self.text_entry.handler_unblock_by_func(
+ self.auto_completer.on_entry_text_delete_text
+ )
self.text_entry.select_region(0, 0)
self.text_entry.set_position(len(text) if cursor_end else 0)
@@ -1111,7 +1206,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
self.combo_hbox.set_tooltip_text(text)
if default_text:
self.default_text = text
- self.button_default.set_tooltip_text('Restore the default value in the text entry:\n%s' % self.default_text)
+ self.button_default.set_tooltip_text(
+ 'Restore the default value in the text entry:\n%s' % self.default_text
+ )
self.button_default.set_sensitive(True)
# Set text for the filechooser dialog button
folder_name = ''
@@ -1261,9 +1358,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
"""
self.auto_completer._end_completion(args)
-##############
-# Callbacks and internal functions
-##############
+ ##############
+ # Callbacks and internal functions
+ ##############
def on_entry_text_changed(self, entry):
self.emit('text-changed', self.get_text())
@@ -1274,15 +1371,21 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
def _set_path_entry_filechooser_widths(self):
if self.path_entry_visible:
- self.combo_hbox.set_child_packing(self.filechooser_button, 0, 0, 0, gtk.PACK_START)
+ self.combo_hbox.set_child_packing(
+ self.filechooser_button, 0, 0, 0, gtk.PACK_START
+ )
width, height = self.folder_name_label.get_size_request()
width = 120
if not self.show_folder_name_on_button:
width = 0
self.folder_name_label.set_size_request(width, height)
- self.combo_hbox.set_child_packing(self.filechooser_button, 0, 0, 0, gtk.PACK_START)
+ self.combo_hbox.set_child_packing(
+ self.filechooser_button, 0, 0, 0, gtk.PACK_START
+ )
else:
- self.combo_hbox.set_child_packing(self.filechooser_button, 1, 1, 0, gtk.PACK_START)
+ self.combo_hbox.set_child_packing(
+ self.filechooser_button, 1, 1, 0, gtk.PACK_START
+ )
self.folder_name_label.set_size_request(-1, -1)
# Update text on the button label
self.set_text(self.get_text())
@@ -1319,10 +1422,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
# Select new row with arrow up/down is pressed
if key_is_up_or_down(keyval):
- self.handle_list_scroll(
- _next=key_is_down(keyval),
- set_entry=True,
- )
+ self.handle_list_scroll(_next=key_is_down(keyval), set_entry=True)
return True
elif self.auto_completer.is_auto_completion_accelerator(keyval, state):
if self.auto_completer.auto_complete_enabled:
@@ -1338,7 +1438,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
# Swap the show hidden files value on CTRL-h
if is_ascii_value(keyval, 'h'):
# Set show/hide hidden files
- self.set_show_hidden_files(not self.get_show_hidden_files(), emit_event=True)
+ self.set_show_hidden_files(
+ not self.get_show_hidden_files(), emit_event=True
+ )
return True
elif is_ascii_value(keyval, 's'):
super(PathChooserComboBox, self).add_current_value_to_saved_list()
@@ -1363,9 +1465,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
self.button_toggle.set_active(False)
self._stored_values_popping_down = False
-##############
-# Config dialog
-##############
+ ##############
+ # Config dialog
+ ##############
def _on_button_toggle_dropdown_button_press_event(self, widget, event):
"""Show config when right clicking dropdown toggle button"""
@@ -1383,10 +1485,14 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
keyval, mask = gtk.accelerator_parse(self.auto_completer.accelerator_string)
self.accelerator_label.set_text(gtk.accelerator_get_label(keyval, mask))
self.visible_rows.set_value(self.get_max_popup_rows())
- self.show_filechooser_checkbutton.set_active(self.get_filechooser_button_visible())
+ self.show_filechooser_checkbutton.set_active(
+ self.get_filechooser_button_visible()
+ )
self.show_path_entry_checkbutton.set_active(self.path_entry_visible)
self.show_hidden_files_checkbutton.set_active(self.get_show_hidden_files())
- self.show_folder_name_on_button_checkbutton.set_active(self.get_show_folder_name_on_button())
+ self.show_folder_name_on_button_checkbutton.set_active(
+ self.get_show_folder_name_on_button()
+ )
self._set_properties_widgets_sensitive(True)
self.config_dialog.show_all()
@@ -1398,18 +1504,30 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
def _setup_config_dialog(self):
self.config_dialog = self.builder.get_object('completion_config_dialog')
- self.enable_completion = self.builder.get_object('enable_auto_completion_checkbutton')
- self.show_filechooser_checkbutton = self.builder.get_object('show_filechooser_checkbutton')
- self.show_path_entry_checkbutton = self.builder.get_object('show_path_entry_checkbutton')
+ self.enable_completion = self.builder.get_object(
+ 'enable_auto_completion_checkbutton'
+ )
+ self.show_filechooser_checkbutton = self.builder.get_object(
+ 'show_filechooser_checkbutton'
+ )
+ self.show_path_entry_checkbutton = self.builder.get_object(
+ 'show_path_entry_checkbutton'
+ )
set_key_button = self.builder.get_object('set_completion_accelerator_button')
default_set_accelerator_tooltip = set_key_button.get_tooltip_text()
- self.config_short_cuts_frame = self.builder.get_object('config_short_cuts_frame')
+ self.config_short_cuts_frame = self.builder.get_object(
+ 'config_short_cuts_frame'
+ )
self.config_general_frame = self.builder.get_object('config_general_frame')
self.accelerator_label = self.builder.get_object('completion_accelerator_label')
self.visible_rows = self.builder.get_object('visible_rows_spinbutton')
self.visible_rows_label = self.builder.get_object('visible_rows_label')
- self.show_hidden_files_checkbutton = self.builder.get_object('show_hidden_files_checkbutton')
- self.show_folder_name_on_button_checkbutton = self.builder.get_object('show_folder_name_on_button_checkbutton')
+ self.show_hidden_files_checkbutton = self.builder.get_object(
+ 'show_hidden_files_checkbutton'
+ )
+ self.show_folder_name_on_button_checkbutton = self.builder.get_object(
+ 'show_folder_name_on_button_checkbutton'
+ )
self.config_dialog.set_transient_for(component.get('MainWindow').window)
def on_close(widget, event=None):
@@ -1421,33 +1539,53 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
def on_enable_completion_toggled(widget):
self.set_auto_complete_enabled(self.enable_completion.get_active())
- self.emit('auto-complete-enabled-toggled', self.enable_completion.get_active())
+ self.emit(
+ 'auto-complete-enabled-toggled', self.enable_completion.get_active()
+ )
def on_show_filechooser_toggled(widget):
- self.set_filechooser_button_visible(self.show_filechooser_checkbutton.get_active())
- self.emit('show-filechooser-toggled', self.show_filechooser_checkbutton.get_active())
- self.show_folder_name_on_button_checkbutton.set_sensitive(self.show_path_entry_checkbutton.get_active() and
- self.show_filechooser_checkbutton.get_active())
+ self.set_filechooser_button_visible(
+ self.show_filechooser_checkbutton.get_active()
+ )
+ self.emit(
+ 'show-filechooser-toggled',
+ self.show_filechooser_checkbutton.get_active(),
+ )
+ self.show_folder_name_on_button_checkbutton.set_sensitive(
+ self.show_path_entry_checkbutton.get_active()
+ and self.show_filechooser_checkbutton.get_active()
+ )
if not self.filechooser_visible and not self.path_entry_visible:
self.show_path_entry_checkbutton.set_active(True)
on_show_path_entry_toggled(None)
def on_show_path_entry_toggled(widget):
self.set_path_entry_visible(self.show_path_entry_checkbutton.get_active())
- self.emit('show-path-entry-toggled', self.show_path_entry_checkbutton.get_active())
- self.show_folder_name_on_button_checkbutton.set_sensitive(self.show_path_entry_checkbutton.get_active() and
- self.show_filechooser_checkbutton.get_active())
+ self.emit(
+ 'show-path-entry-toggled', self.show_path_entry_checkbutton.get_active()
+ )
+ self.show_folder_name_on_button_checkbutton.set_sensitive(
+ self.show_path_entry_checkbutton.get_active()
+ and self.show_filechooser_checkbutton.get_active()
+ )
if not self.filechooser_visible and not self.path_entry_visible:
self.show_filechooser_checkbutton.set_active(True)
on_show_filechooser_toggled(None)
def on_show_folder_name_on_button(widget):
- self.set_show_folder_name_on_button(self.show_folder_name_on_button_checkbutton.get_active())
+ self.set_show_folder_name_on_button(
+ self.show_folder_name_on_button_checkbutton.get_active()
+ )
self._set_path_entry_filechooser_widths()
- self.emit('show-folder-name-on-button', self.show_folder_name_on_button_checkbutton.get_active())
+ self.emit(
+ 'show-folder-name-on-button',
+ self.show_folder_name_on_button_checkbutton.get_active(),
+ )
def on_show_hidden_files_toggled(widget):
- self.set_show_hidden_files(self.show_hidden_files_checkbutton.get_active(), emit_event=True)
+ self.set_show_hidden_files(
+ self.show_hidden_files_checkbutton.get_active(), emit_event=True
+ )
def on_max_rows_changed(widget):
self.set_max_popup_rows(self.visible_rows.get_value_as_int())
@@ -1455,7 +1593,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
def set_accelerator(widget):
self.setting_accelerator_key = True
- set_key_button.set_tooltip_text('Press the accelerator keys for triggering auto-completion')
+ set_key_button.set_tooltip_text(
+ 'Press the accelerator keys for triggering auto-completion'
+ )
self._set_properties_widgets_sensitive(False)
return True
@@ -1474,8 +1614,12 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
# If e.g. only CTRL key is pressed.
if not gtk.accelerator_valid(event.keyval, accelerator_mask):
accelerator_mask = 0
- self.auto_completer.accelerator_string = gtk.accelerator_name(event.keyval, accelerator_mask)
- self.accelerator_label.set_text(gtk.accelerator_get_label(event.keyval, accelerator_mask))
+ self.auto_completer.accelerator_string = gtk.accelerator_name(
+ event.keyval, accelerator_mask
+ )
+ self.accelerator_label.set_text(
+ gtk.accelerator_get_label(event.keyval, accelerator_mask)
+ )
self.emit('accelerator-set', self.auto_completer.accelerator_string)
stop_setting_accelerator()
return True
@@ -1485,7 +1629,9 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
if ctrl:
# Set show/hide hidden files
if is_ascii_value(keyval, 'h'):
- self.show_hidden_files_checkbutton.set_active(not self.get_show_hidden_files())
+ self.show_hidden_files_checkbutton.set_active(
+ not self.get_show_hidden_files()
+ )
return True
def on_set_completion_accelerator_button_clicked(widget):
@@ -1513,6 +1659,7 @@ type_register(PathChooserComboBox)
if __name__ == '__main__':
import sys
+
w = gtk.Window()
w.set_position(gtk.WIN_POS_CENTER)
w.set_size_request(600, -1)
diff --git a/deluge/ui/gtkui/peers_tab.py b/deluge/ui/gtkui/peers_tab.py
index ca2fd6366..5966564a6 100644
--- a/deluge/ui/gtkui/peers_tab.py
+++ b/deluge/ui/gtkui/peers_tab.py
@@ -12,17 +12,33 @@ from __future__ import unicode_literals
import logging
import os.path
-from gtk import (TREE_VIEW_COLUMN_FIXED, Builder, CellRendererPixbuf, CellRendererProgress, CellRendererText, ListStore,
- TreeViewColumn)
+from gtk import (
+ TREE_VIEW_COLUMN_FIXED,
+ Builder,
+ CellRendererPixbuf,
+ CellRendererProgress,
+ CellRendererText,
+ ListStore,
+ TreeViewColumn,
+)
from gtk.gdk import Pixbuf, pixbuf_new_from_file
import deluge.common
import deluge.component as component
from deluge.ui.client import client
from deluge.ui.countries import COUNTRIES
-from deluge.ui.gtkui.common import icon_downloading, icon_seeding, load_pickled_state_file, save_pickled_state_file
+from deluge.ui.gtkui.common import (
+ icon_downloading,
+ icon_seeding,
+ load_pickled_state_file,
+ save_pickled_state_file,
+)
from deluge.ui.gtkui.torrentdetails import Tab
-from deluge.ui.gtkui.torrentview_data_funcs import cell_data_peer_progress, cell_data_speed_down, cell_data_speed_up
+from deluge.ui.gtkui.torrentview_data_funcs import (
+ cell_data_peer_progress,
+ cell_data_speed_down,
+ cell_data_speed_up,
+)
try:
from future_builtins import zip
@@ -46,7 +62,9 @@ class PeersTab(Tab):
self.listview.connect('query-tooltip', self._on_query_tooltip)
# flag, ip, client, downspd, upspd, country code, int_ip, seed/peer icon, progress
- self.liststore = ListStore(Pixbuf, str, str, int, int, str, float, Pixbuf, float)
+ self.liststore = ListStore(
+ Pixbuf, str, str, int, int, str, float, Pixbuf, float
+ )
self.cached_flag_pixbufs = {}
self.seed_pixbuf = icon_seeding
@@ -188,8 +206,13 @@ class PeersTab(Tab):
# Column is in wrong position
if cstate['position'] == 0:
self.listview.move_column_after(column, None)
- elif self.listview.get_columns()[cstate['position'] - 1].get_title() != cname:
- self.listview.move_column_after(column, self.listview.get_columns()[cstate['position'] - 1])
+ elif (
+ self.listview.get_columns()[cstate['position'] - 1].get_title()
+ != cname
+ ):
+ self.listview.move_column_after(
+ column, self.listview.get_columns()[cstate['position'] - 1]
+ )
def update(self):
# Get the first selected torrent
@@ -209,7 +232,9 @@ class PeersTab(Tab):
self.peers = {}
self.torrent_id = torrent_id
- component.get('SessionProxy').get_torrent_status(torrent_id, ['peers']).addCallback(self._on_get_torrent_status)
+ component.get('SessionProxy').get_torrent_status(
+ torrent_id, ['peers']
+ ).addCallback(self._on_get_torrent_status)
def get_flag_pixbuf(self, country):
if not country.strip():
@@ -221,8 +246,10 @@ class PeersTab(Tab):
self.cached_flag_pixbufs[country] = pixbuf_new_from_file(
deluge.common.resource_filename(
'deluge',
- os.path.join('ui', 'data', 'pixmaps', 'flags', country.lower() + '.png'),
- ),
+ os.path.join(
+ 'ui', 'data', 'pixmaps', 'flags', country.lower() + '.png'
+ ),
+ )
)
except Exception as ex:
log.debug('Unable to load flag: %s', ex)
@@ -248,7 +275,9 @@ class PeersTab(Tab):
self.liststore.set_value(row, 4, peer['up_speed'])
if peer['country'] != values[2]:
self.liststore.set_value(row, 5, peer['country'])
- self.liststore.set_value(row, 0, self.get_flag_pixbuf(peer['country']))
+ self.liststore.set_value(
+ row, 0, self.get_flag_pixbuf(peer['country'])
+ )
if peer['seed']:
icon = self.seed_pixbuf
else:
@@ -267,16 +296,21 @@ class PeersTab(Tab):
# This is an IPv4 address
ip_int = sum(
int(byte) << shift
- for byte, shift in zip(peer['ip'].split(':')[0].split('.'), (24, 16, 8, 0))
+ for byte, shift in zip(
+ peer['ip'].split(':')[0].split('.'), (24, 16, 8, 0)
+ )
)
peer_ip = peer['ip']
else:
# This is an IPv6 address
import socket
import binascii
+
# Split out the :port
ip = ':'.join(peer['ip'].split(':')[:-1])
- ip_int = int(binascii.hexlify(socket.inet_pton(socket.AF_INET6, ip)), 16)
+ ip_int = int(
+ binascii.hexlify(socket.inet_pton(socket.AF_INET6, ip)), 16
+ )
peer_ip = '[%s]:%s' % (ip, peer['ip'].split(':')[-1])
if peer['seed']:
@@ -284,17 +318,19 @@ class PeersTab(Tab):
else:
icon = self.peer_pixbuf
- row = self.liststore.append([
- self.get_flag_pixbuf(peer['country']),
- peer_ip,
- peer['client'],
- peer['down_speed'],
- peer['up_speed'],
- peer['country'],
- float(ip_int),
- icon,
- peer['progress'],
- ])
+ row = self.liststore.append(
+ [
+ self.get_flag_pixbuf(peer['country']),
+ peer_ip,
+ peer['client'],
+ peer['down_speed'],
+ peer['up_speed'],
+ peer['country'],
+ float(ip_int),
+ icon,
+ peer['progress'],
+ ]
+ )
self.peers[peer['ip']] = row
@@ -324,10 +360,7 @@ class PeersTab(Tab):
if country_code != ' ' and country_code in COUNTRIES:
tooltip.set_text(COUNTRIES[country_code])
# widget here is self.listview
- widget.set_tooltip_cell(
- tooltip, path, widget.get_column(0),
- None,
- )
+ widget.set_tooltip_cell(tooltip, path, widget.get_column(0), None)
return True
else:
return False
@@ -336,9 +369,11 @@ class PeersTab(Tab):
"""This is a callback for manually adding a peer"""
log.debug('on_menuitem_add_peer')
builder = Builder()
- builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'connect_peer_dialog.ui'),
- ))
+ builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'connect_peer_dialog.ui')
+ )
+ )
peer_dialog = builder.get_object('connect_peer_dialog')
txt_ip = builder.get_object('txt_ip')
response = peer_dialog.run()
diff --git a/deluge/ui/gtkui/piecesbar.py b/deluge/ui/gtkui/piecesbar.py
index 2819540a4..8893c6946 100644
--- a/deluge/ui/gtkui/piecesbar.py
+++ b/deluge/ui/gtkui/piecesbar.py
@@ -82,7 +82,9 @@ class PiecesBar(DrawingArea):
self.cr.clip()
def roundcorners_border(self):
- self.create_roundcorners_subpath(self.cr, 0.5, 0.5, self.width - 1, self.height - 1)
+ self.create_roundcorners_subpath(
+ self.cr, 0.5, 0.5, self.width - 1, self.height - 1
+ )
self.cr.set_source_rgba(0, 0, 0, 0.9)
self.cr.stroke()
@@ -94,7 +96,9 @@ class PiecesBar(DrawingArea):
degrees = pi / 180
ctx.new_sub_path()
ctx.arc(x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees)
- ctx.arc(x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees)
+ ctx.arc(
+ x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees
+ )
ctx.arc(x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees)
ctx.arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees)
ctx.close_path()
@@ -105,7 +109,11 @@ class PiecesBar(DrawingArea):
# Nothing to draw.
return
- if self.resized() or self.pieces != self.prev_pieces or self.pieces_overlay is None:
+ if (
+ self.resized()
+ or self.pieces != self.prev_pieces
+ or self.pieces_overlay is None
+ ):
# Need to recreate the cache drawing
self.pieces_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height)
ctx = Context(self.pieces_overlay)
@@ -118,7 +126,10 @@ class PiecesBar(DrawingArea):
start_pos = 0
piece_width = self.width / len(pieces)
pieces_colors = [
- [color / 65535 for color in self.gtkui_config['pieces_color_%s' % state]]
+ [
+ color / 65535
+ for color in self.gtkui_config['pieces_color_%s' % state]
+ ]
for state in COLOR_STATES
]
for state in pieces:
@@ -135,7 +146,11 @@ class PiecesBar(DrawingArea):
# Nothing useful to draw, return now!
return
- if self.resized() or self.fraction != self.prev_fraction or self.progress_overlay is None:
+ if (
+ self.resized()
+ or self.fraction != self.prev_fraction
+ or self.progress_overlay is None
+ ):
# Need to recreate the cache drawing
self.progress_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height)
ctx = Context(self.progress_overlay)
diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py
index f1424a693..986a60aa5 100644
--- a/deluge/ui/gtkui/pluginmanager.py
+++ b/deluge/ui/gtkui/pluginmanager.py
@@ -24,16 +24,17 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
component.Component.__init__(self, 'PluginManager')
self.config = ConfigManager('gtkui.conf')
deluge.pluginmanagerbase.PluginManagerBase.__init__(
- self, 'gtkui.conf', 'deluge.plugin.gtkui',
+ self, 'gtkui.conf', 'deluge.plugin.gtkui'
)
- self.hooks = {
- 'on_apply_prefs': [],
- 'on_show_prefs': [],
- }
+ self.hooks = {'on_apply_prefs': [], 'on_show_prefs': []}
- client.register_event_handler('PluginEnabledEvent', self._on_plugin_enabled_event)
- client.register_event_handler('PluginDisabledEvent', self._on_plugin_disabled_event)
+ client.register_event_handler(
+ 'PluginEnabledEvent', self._on_plugin_enabled_event
+ )
+ client.register_event_handler(
+ 'PluginDisabledEvent', self._on_plugin_disabled_event
+ )
def register_hook(self, hook, function):
"""Register a hook function with the plugin manager"""
diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py
index f1832f0e6..be011efac 100644
--- a/deluge/ui/gtkui/preferences.py
+++ b/deluge/ui/gtkui/preferences.py
@@ -23,8 +23,17 @@ from deluge.configmanager import ConfigManager, get_config_dir
from deluge.error import AuthManagerError, NotAuthorizedError
from deluge.ui.client import client
from deluge.ui.common import DISK_CACHE_KEYS, PREFS_CATOG_TRANS
-from deluge.ui.gtkui.common import associate_magnet_links, get_clipboard_text, get_deluge_icon
-from deluge.ui.gtkui.dialogs import AccountDialog, ErrorDialog, InformationDialog, YesNoDialog
+from deluge.ui.gtkui.common import (
+ associate_magnet_links,
+ get_clipboard_text,
+ get_deluge_icon,
+)
+from deluge.ui.gtkui.dialogs import (
+ AccountDialog,
+ ErrorDialog,
+ InformationDialog,
+ YesNoDialog,
+)
from deluge.ui.gtkui.path_chooser import PathChooser
from deluge.ui.translations_util import get_languages
@@ -56,9 +65,11 @@ class Preferences(component.Component):
def __init__(self):
component.Component.__init__(self, 'Preferences')
self.builder = gtk.Builder()
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'preferences_dialog.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'preferences_dialog.ui')
+ )
+ )
self.pref_dialog = self.builder.get_object('pref_dialog')
self.pref_dialog.set_transient_for(component.get('MainWindow').window)
self.pref_dialog.set_icon(get_deluge_icon())
@@ -70,7 +81,7 @@ class Preferences(component.Component):
self.load_pref_dialog_state()
self.builder.get_object('image_magnet').set_from_file(
- deluge.common.get_pixmap('magnet.png'),
+ deluge.common.get_pixmap('magnet.png')
)
# Hide the unused associate magnet button on OSX see: #2420
@@ -86,8 +97,16 @@ class Preferences(component.Component):
# Add the default categories
prefs_categories = (
- 'interface', 'downloads', 'bandwidth', 'queue', 'network', 'proxy',
- 'cache', 'other', 'daemon', 'plugins',
+ 'interface',
+ 'downloads',
+ 'bandwidth',
+ 'queue',
+ 'network',
+ 'proxy',
+ 'cache',
+ 'other',
+ 'daemon',
+ 'plugins',
)
for idx, category in enumerate(prefs_categories):
self.liststore.append([idx, category, PREFS_CATOG_TRANS[category]])
@@ -96,6 +115,7 @@ class Preferences(component.Component):
def set_separator(model, _iter, data=None):
if model.get_value(_iter, 1) == '_separator_':
return True
+
self.treeview.set_row_separator_func(set_separator, None)
self.liststore.append([len(self.liststore), '_separator_', ''])
# Add a dummy notebook page to keep indexing synced with liststore.
@@ -105,20 +125,28 @@ class Preferences(component.Component):
self.accounts_levels_mapping = None
self.accounts_authlevel = self.builder.get_object('accounts_authlevel')
self.accounts_liststore = gtk.ListStore(str, str, str, int)
- self.accounts_liststore.set_sort_column_id(ACCOUNTS_USERNAME, gtk.SORT_ASCENDING)
+ self.accounts_liststore.set_sort_column_id(
+ ACCOUNTS_USERNAME, gtk.SORT_ASCENDING
+ )
self.accounts_listview = self.builder.get_object('accounts_listview')
self.accounts_listview.append_column(
- gtk.TreeViewColumn(_('Username'), gtk.CellRendererText(), text=ACCOUNTS_USERNAME),
+ gtk.TreeViewColumn(
+ _('Username'), gtk.CellRendererText(), text=ACCOUNTS_USERNAME
+ )
)
self.accounts_listview.append_column(
- gtk.TreeViewColumn(_('Level'), gtk.CellRendererText(), text=ACCOUNTS_LEVEL),
+ gtk.TreeViewColumn(_('Level'), gtk.CellRendererText(), text=ACCOUNTS_LEVEL)
+ )
+ password_column = gtk.TreeViewColumn(
+ 'password', gtk.CellRendererText(), text=ACCOUNTS_PASSWORD
)
- password_column = gtk.TreeViewColumn('password', gtk.CellRendererText(), text=ACCOUNTS_PASSWORD)
self.accounts_listview.append_column(password_column)
password_column.set_visible(False)
self.accounts_listview.set_model(self.accounts_liststore)
- self.accounts_listview.get_selection().connect('changed', self.on_accounts_selection_changed)
+ self.accounts_listview.get_selection().connect(
+ 'changed', self.on_accounts_selection_changed
+ )
self.accounts_frame = self.builder.get_object('AccountsFrame')
# Setup plugin tab listview
@@ -130,14 +158,20 @@ class Preferences(component.Component):
render = gtk.CellRendererToggle()
render.connect('toggled', self.on_plugin_toggled)
render.set_property('activatable', True)
- self.plugin_listview.append_column(gtk.TreeViewColumn(_('Enabled'), render, active=1))
- self.plugin_listview.append_column(gtk.TreeViewColumn(_('Plugin'), gtk.CellRendererText(), text=2))
+ self.plugin_listview.append_column(
+ gtk.TreeViewColumn(_('Enabled'), render, active=1)
+ )
+ self.plugin_listview.append_column(
+ gtk.TreeViewColumn(_('Plugin'), gtk.CellRendererText(), text=2)
+ )
# Connect to the 'changed' event of TreeViewSelection to get selection
# changes.
self.treeview.get_selection().connect('changed', self.on_selection_changed)
- self.plugin_listview.get_selection().connect('changed', self.on_plugin_selection_changed)
+ self.plugin_listview.get_selection().connect(
+ 'changed', self.on_plugin_selection_changed
+ )
self.builder.connect_signals(self)
@@ -145,6 +179,7 @@ class Preferences(component.Component):
self.builder.get_object('alignment_tray_type').set_visible(bool(appindicator))
from deluge.ui.gtkui.gtkui import DEFAULT_PREFS
+
self.COLOR_DEFAULTS = {}
for key in ('missing', 'waiting', 'downloading', 'completed'):
self.COLOR_DEFAULTS[key] = DEFAULT_PREFS['pieces_color_%s' % key][:]
@@ -158,18 +193,28 @@ class Preferences(component.Component):
self.load_languages()
def setup_path_choosers(self):
- self.download_location_hbox = self.builder.get_object('hbox_download_to_path_chooser')
- self.download_location_path_chooser = PathChooser('download_location_paths_list')
+ self.download_location_hbox = self.builder.get_object(
+ 'hbox_download_to_path_chooser'
+ )
+ self.download_location_path_chooser = PathChooser(
+ 'download_location_paths_list'
+ )
self.download_location_hbox.add(self.download_location_path_chooser)
self.download_location_hbox.show_all()
- self.move_completed_hbox = self.builder.get_object('hbox_move_completed_to_path_chooser')
+ self.move_completed_hbox = self.builder.get_object(
+ 'hbox_move_completed_to_path_chooser'
+ )
self.move_completed_path_chooser = PathChooser('move_completed_paths_list')
self.move_completed_hbox.add(self.move_completed_path_chooser)
self.move_completed_hbox.show_all()
- self.copy_torrents_to_hbox = self.builder.get_object('hbox_copy_torrent_files_path_chooser')
- self.copy_torrent_files_path_chooser = PathChooser('copy_torrent_files_to_paths_list')
+ self.copy_torrents_to_hbox = self.builder.get_object(
+ 'hbox_copy_torrent_files_path_chooser'
+ )
+ self.copy_torrent_files_path_chooser = PathChooser(
+ 'copy_torrent_files_to_paths_list'
+ )
self.copy_torrents_to_hbox.add(self.copy_torrent_files_path_chooser)
self.copy_torrents_to_hbox.show_all()
@@ -273,7 +318,9 @@ class Preferences(component.Component):
def on_get_config(config):
self.core_config = config
- client.core.get_available_plugins().addCallback(on_get_available_plugins)
+ client.core.get_available_plugins().addCallback(
+ on_get_available_plugins
+ )
def on_get_available_plugins(plugins):
self.all_plugins = plugins
@@ -285,7 +332,9 @@ class Preferences(component.Component):
def on_get_listen_port(port):
self.active_port = port
- client.core.get_session_status(DISK_CACHE_KEYS).addCallback(on_get_session_status)
+ client.core.get_session_status(DISK_CACHE_KEYS).addCallback(
+ on_get_session_status
+ )
def on_get_session_status(status):
self.cache_status = status
@@ -312,14 +361,26 @@ class Preferences(component.Component):
'chk_copy_torrent_file': ('active', 'copy_torrent_file'),
'chk_del_copy_torrent_file': ('active', 'del_copy_torrent_file'),
'chk_pre_allocation': ('active', 'pre_allocate_storage'),
- 'chk_prioritize_first_last_pieces': ('active', 'prioritize_first_last_pieces'),
+ 'chk_prioritize_first_last_pieces': (
+ 'active',
+ 'prioritize_first_last_pieces',
+ ),
'chk_sequential_download': ('active', 'sequential_download'),
'chk_add_paused': ('active', 'add_paused'),
'active_port_label': ('text', lambda: str(self.active_port)),
- 'spin_incoming_port': ('value', lambda: self.core_config['listen_ports'][0]),
+ 'spin_incoming_port': (
+ 'value',
+ lambda: self.core_config['listen_ports'][0],
+ ),
'chk_random_incoming_port': ('active', 'random_port'),
- 'spin_outgoing_port_min': ('value', lambda: self.core_config['outgoing_ports'][0]),
- 'spin_outgoing_port_max': ('value', lambda: self.core_config['outgoing_ports'][1]),
+ 'spin_outgoing_port_min': (
+ 'value',
+ lambda: self.core_config['outgoing_ports'][0],
+ ),
+ 'spin_outgoing_port_max': (
+ 'value',
+ lambda: self.core_config['outgoing_ports'][1],
+ ),
'chk_random_outgoing_ports': ('active', 'random_outgoing_ports'),
'entry_interface': ('text', 'listen_interface'),
'entry_outgoing_interface': ('text', 'outgoing_interface'),
@@ -341,12 +402,23 @@ class Preferences(component.Component):
'spin_max_upload_slots_global': ('value', 'max_upload_slots_global'),
'spin_max_half_open_connections': ('value', 'max_connections_per_second'),
'spin_max_connections_per_second': ('value', 'max_connections_per_second'),
- 'chk_ignore_limits_on_local_network': ('active', 'ignore_limits_on_local_network'),
+ 'chk_ignore_limits_on_local_network': (
+ 'active',
+ 'ignore_limits_on_local_network',
+ ),
'chk_rate_limit_ip_overhead': ('active', 'rate_limit_ip_overhead'),
-
- 'spin_max_connections_per_torrent': ('value', 'max_connections_per_torrent'),
- 'spin_max_upload_slots_per_torrent': ('value', 'max_upload_slots_per_torrent'),
- 'spin_max_download_per_torrent': ('value', 'max_download_speed_per_torrent'),
+ 'spin_max_connections_per_torrent': (
+ 'value',
+ 'max_connections_per_torrent',
+ ),
+ 'spin_max_upload_slots_per_torrent': (
+ 'value',
+ 'max_upload_slots_per_torrent',
+ ),
+ 'spin_max_download_per_torrent': (
+ 'value',
+ 'max_download_speed_per_torrent',
+ ),
'spin_max_upload_per_torrent': ('value', 'max_upload_speed_per_torrent'),
'spin_daemon_port': ('value', 'daemon_port'),
'chk_allow_remote_connections': ('active', 'allow_remote'),
@@ -370,11 +442,26 @@ class Preferences(component.Component):
'entry_proxy_pass': ('text', lambda: self.core_config['proxy']['password']),
'entry_proxy_host': ('text', lambda: self.core_config['proxy']['hostname']),
'spin_proxy_port': ('value', lambda: self.core_config['proxy']['port']),
- 'chk_proxy_host_resolve': ('active', lambda: self.core_config['proxy']['proxy_hostnames']),
- 'chk_proxy_peer_conn': ('active', lambda: self.core_config['proxy']['proxy_peer_connections']),
- 'chk_proxy_tracker_conn': ('active', lambda: self.core_config['proxy']['proxy_tracker_connections']),
- 'chk_force_proxy': ('active', lambda: self.core_config['proxy']['force_proxy']),
- 'chk_anonymous_mode': ('active', lambda: self.core_config['proxy']['anonymous_mode']),
+ 'chk_proxy_host_resolve': (
+ 'active',
+ lambda: self.core_config['proxy']['proxy_hostnames'],
+ ),
+ 'chk_proxy_peer_conn': (
+ 'active',
+ lambda: self.core_config['proxy']['proxy_peer_connections'],
+ ),
+ 'chk_proxy_tracker_conn': (
+ 'active',
+ lambda: self.core_config['proxy']['proxy_tracker_connections'],
+ ),
+ 'chk_force_proxy': (
+ 'active',
+ lambda: self.core_config['proxy']['force_proxy'],
+ ),
+ 'chk_anonymous_mode': (
+ 'active',
+ lambda: self.core_config['proxy']['anonymous_mode'],
+ ),
'accounts_add': (None, None),
'accounts_listview': (None, None),
'button_cache_refresh': (None, None),
@@ -385,9 +472,18 @@ class Preferences(component.Component):
'plugin_listview': (None, None),
}
- core_widgets[self.download_location_path_chooser] = ('path_chooser', 'download_location')
- core_widgets[self.move_completed_path_chooser] = ('path_chooser', 'move_completed_path')
- core_widgets[self.copy_torrent_files_path_chooser] = ('path_chooser', 'torrentfiles_location')
+ core_widgets[self.download_location_path_chooser] = (
+ 'path_chooser',
+ 'download_location',
+ )
+ core_widgets[self.move_completed_path_chooser] = (
+ 'path_chooser',
+ 'move_completed_path',
+ )
+ core_widgets[self.copy_torrent_files_path_chooser] = (
+ 'path_chooser',
+ 'torrentfiles_location',
+ )
# Update the widgets accordingly
for key in core_widgets:
@@ -407,7 +503,13 @@ class Preferences(component.Component):
if callable(value):
value = value()
elif modifier:
- value = {'active': False, 'not_active': False, 'value': 0, 'text': '', 'path_chooser': ''}[modifier]
+ value = {
+ 'active': False,
+ 'not_active': False,
+ 'value': 0,
+ 'text': '',
+ 'path_chooser': '',
+ }[modifier]
if modifier == 'active':
widget.set_active(value)
@@ -432,29 +534,53 @@ class Preferences(component.Component):
self.on_toggle(widget)
# Downloads tab #
- self.builder.get_object('chk_show_dialog').set_active(self.gtkui_config['interactive_add'])
- self.builder.get_object('chk_focus_dialog').set_active(self.gtkui_config['focus_add_dialog'])
+ self.builder.get_object('chk_show_dialog').set_active(
+ self.gtkui_config['interactive_add']
+ )
+ self.builder.get_object('chk_focus_dialog').set_active(
+ self.gtkui_config['focus_add_dialog']
+ )
# Interface tab #
- self.builder.get_object('chk_use_tray').set_active(self.gtkui_config['enable_system_tray'])
- self.builder.get_object('chk_min_on_close').set_active(self.gtkui_config['close_to_tray'])
- self.builder.get_object('chk_start_in_tray').set_active(self.gtkui_config['start_in_tray'])
- self.builder.get_object('radio_appind').set_active(self.gtkui_config['enable_appindicator'])
- self.builder.get_object('chk_lock_tray').set_active(self.gtkui_config['lock_tray'])
- self.builder.get_object('radio_standalone').set_active(self.gtkui_config['standalone'])
- self.builder.get_object('radio_thinclient').set_active(not self.gtkui_config['standalone'])
- self.builder.get_object('chk_show_rate_in_title').set_active(self.gtkui_config['show_rate_in_title'])
+ self.builder.get_object('chk_use_tray').set_active(
+ self.gtkui_config['enable_system_tray']
+ )
+ self.builder.get_object('chk_min_on_close').set_active(
+ self.gtkui_config['close_to_tray']
+ )
+ self.builder.get_object('chk_start_in_tray').set_active(
+ self.gtkui_config['start_in_tray']
+ )
+ self.builder.get_object('radio_appind').set_active(
+ self.gtkui_config['enable_appindicator']
+ )
+ self.builder.get_object('chk_lock_tray').set_active(
+ self.gtkui_config['lock_tray']
+ )
+ self.builder.get_object('radio_standalone').set_active(
+ self.gtkui_config['standalone']
+ )
+ self.builder.get_object('radio_thinclient').set_active(
+ not self.gtkui_config['standalone']
+ )
+ self.builder.get_object('chk_show_rate_in_title').set_active(
+ self.gtkui_config['show_rate_in_title']
+ )
self.builder.get_object('chk_focus_main_window_on_add').set_active(
- self.gtkui_config['focus_main_window_on_add'],
+ self.gtkui_config['focus_main_window_on_add']
+ )
+ self.builder.get_object('piecesbar_toggle').set_active(
+ self.gtkui_config['show_piecesbar']
)
- self.builder.get_object('piecesbar_toggle').set_active(self.gtkui_config['show_piecesbar'])
self.__set_color('completed', from_config=True)
self.__set_color('downloading', from_config=True)
self.__set_color('waiting', from_config=True)
self.__set_color('missing', from_config=True)
# Other tab #
- self.builder.get_object('chk_show_new_releases').set_active(self.gtkui_config['show_new_releases'])
+ self.builder.get_object('chk_show_new_releases').set_active(
+ self.gtkui_config['show_new_releases']
+ )
# Cache tab #
if client.connected():
@@ -488,107 +614,152 @@ class Preferences(component.Component):
new_gtkui_config = {}
# Downloads tab #
- new_gtkui_config['interactive_add'] = self.builder.get_object('chk_show_dialog').get_active()
- new_gtkui_config['focus_add_dialog'] = self.builder.get_object('chk_focus_dialog').get_active()
+ new_gtkui_config['interactive_add'] = self.builder.get_object(
+ 'chk_show_dialog'
+ ).get_active()
+ new_gtkui_config['focus_add_dialog'] = self.builder.get_object(
+ 'chk_focus_dialog'
+ ).get_active()
for state in ('missing', 'waiting', 'downloading', 'completed'):
color = self.builder.get_object('%s_color' % state).get_color()
new_gtkui_config['pieces_color_%s' % state] = [
- color.red, color.green, color.blue,
+ color.red,
+ color.green,
+ color.blue,
]
new_core_config['copy_torrent_file'] = self.builder.get_object(
- 'chk_copy_torrent_file',
+ 'chk_copy_torrent_file'
).get_active()
new_core_config['del_copy_torrent_file'] = self.builder.get_object(
- 'chk_del_copy_torrent_file',
+ 'chk_del_copy_torrent_file'
+ ).get_active()
+ new_core_config['move_completed'] = self.builder.get_object(
+ 'chk_move_completed'
).get_active()
- new_core_config['move_completed'] = self.builder.get_object('chk_move_completed').get_active()
- new_core_config['download_location'] = self.download_location_path_chooser.get_text()
- new_core_config['move_completed_path'] = self.move_completed_path_chooser.get_text()
- new_core_config['torrentfiles_location'] = self.copy_torrent_files_path_chooser.get_text()
+ new_core_config[
+ 'download_location'
+ ] = self.download_location_path_chooser.get_text()
+ new_core_config[
+ 'move_completed_path'
+ ] = self.move_completed_path_chooser.get_text()
+ new_core_config[
+ 'torrentfiles_location'
+ ] = self.copy_torrent_files_path_chooser.get_text()
new_core_config['prioritize_first_last_pieces'] = self.builder.get_object(
- 'chk_prioritize_first_last_pieces',
+ 'chk_prioritize_first_last_pieces'
).get_active()
new_core_config['sequential_download'] = self.builder.get_object(
- 'chk_sequential_download',
+ 'chk_sequential_download'
+ ).get_active()
+ new_core_config['add_paused'] = self.builder.get_object(
+ 'chk_add_paused'
).get_active()
- new_core_config['add_paused'] = self.builder.get_object('chk_add_paused').get_active()
new_core_config['pre_allocate_storage'] = self.builder.get_object(
- 'chk_pre_allocation',
+ 'chk_pre_allocation'
).get_active()
# Network tab #
- listen_ports = [self.builder.get_object('spin_incoming_port').get_value_as_int()] * 2
+ listen_ports = [
+ self.builder.get_object('spin_incoming_port').get_value_as_int()
+ ] * 2
new_core_config['listen_ports'] = listen_ports
- new_core_config['random_port'] = self.builder.get_object('chk_random_incoming_port').get_active()
+ new_core_config['random_port'] = self.builder.get_object(
+ 'chk_random_incoming_port'
+ ).get_active()
outgoing_ports = (
self.builder.get_object('spin_outgoing_port_min').get_value_as_int(),
self.builder.get_object('spin_outgoing_port_max').get_value_as_int(),
)
new_core_config['outgoing_ports'] = outgoing_ports
new_core_config['random_outgoing_ports'] = self.builder.get_object(
- 'chk_random_outgoing_ports',
+ 'chk_random_outgoing_ports'
).get_active()
incoming_address = self.builder.get_object('entry_interface').get_text().strip()
if deluge.common.is_ip(incoming_address) or not incoming_address:
new_core_config['listen_interface'] = incoming_address
- outgoing_interface = self.builder.get_object(
- 'entry_outgoing_interface').get_text().strip()
+ outgoing_interface = (
+ self.builder.get_object('entry_outgoing_interface').get_text().strip()
+ )
if not deluge.common.is_ip(outgoing_interface) or not outgoing_interface:
new_core_config['outgoing_interface'] = outgoing_interface
- new_core_config['peer_tos'] = self.builder.get_object('entry_peer_tos').get_text()
+ new_core_config['peer_tos'] = self.builder.get_object(
+ 'entry_peer_tos'
+ ).get_text()
new_core_config['dht'] = self.builder.get_object('chk_dht').get_active()
new_core_config['upnp'] = self.builder.get_object('chk_upnp').get_active()
new_core_config['natpmp'] = self.builder.get_object('chk_natpmp').get_active()
new_core_config['utpex'] = self.builder.get_object('chk_utpex').get_active()
new_core_config['lsd'] = self.builder.get_object('chk_lsd').get_active()
- new_core_config['enc_in_policy'] = self.builder.get_object('combo_encin').get_active()
- new_core_config['enc_out_policy'] = self.builder.get_object('combo_encout').get_active()
- new_core_config['enc_level'] = self.builder.get_object('combo_enclevel').get_active()
+ new_core_config['enc_in_policy'] = self.builder.get_object(
+ 'combo_encin'
+ ).get_active()
+ new_core_config['enc_out_policy'] = self.builder.get_object(
+ 'combo_encout'
+ ).get_active()
+ new_core_config['enc_level'] = self.builder.get_object(
+ 'combo_enclevel'
+ ).get_active()
# Bandwidth tab #
new_core_config['max_connections_global'] = self.builder.get_object(
- 'spin_max_connections_global',
+ 'spin_max_connections_global'
).get_value_as_int()
- new_core_config['max_download_speed'] = self.builder.get_object('spin_max_download').get_value()
- new_core_config['max_upload_speed'] = self.builder.get_object('spin_max_upload').get_value()
+ new_core_config['max_download_speed'] = self.builder.get_object(
+ 'spin_max_download'
+ ).get_value()
+ new_core_config['max_upload_speed'] = self.builder.get_object(
+ 'spin_max_upload'
+ ).get_value()
new_core_config['max_upload_slots_global'] = self.builder.get_object(
- 'spin_max_upload_slots_global',
+ 'spin_max_upload_slots_global'
).get_value_as_int()
new_core_config['max_half_open_connections'] = self.builder.get_object(
- 'spin_max_half_open_connections',
+ 'spin_max_half_open_connections'
).get_value_as_int()
new_core_config['max_connections_per_second'] = self.builder.get_object(
- 'spin_max_connections_per_second',
+ 'spin_max_connections_per_second'
).get_value_as_int()
new_core_config['max_connections_per_torrent'] = self.builder.get_object(
- 'spin_max_connections_per_torrent',
+ 'spin_max_connections_per_torrent'
).get_value_as_int()
new_core_config['max_upload_slots_per_torrent'] = self.builder.get_object(
- 'spin_max_upload_slots_per_torrent',
+ 'spin_max_upload_slots_per_torrent'
).get_value_as_int()
new_core_config['max_upload_speed_per_torrent'] = self.builder.get_object(
- 'spin_max_upload_per_torrent',
+ 'spin_max_upload_per_torrent'
).get_value()
new_core_config['max_download_speed_per_torrent'] = self.builder.get_object(
- 'spin_max_download_per_torrent',
+ 'spin_max_download_per_torrent'
).get_value()
new_core_config['ignore_limits_on_local_network'] = self.builder.get_object(
- 'chk_ignore_limits_on_local_network',
+ 'chk_ignore_limits_on_local_network'
).get_active()
new_core_config['rate_limit_ip_overhead'] = self.builder.get_object(
- 'chk_rate_limit_ip_overhead',
+ 'chk_rate_limit_ip_overhead'
).get_active()
# Interface tab #
- new_gtkui_config['enable_system_tray'] = self.builder.get_object('chk_use_tray').get_active()
- new_gtkui_config['close_to_tray'] = self.builder.get_object('chk_min_on_close').get_active()
- new_gtkui_config['start_in_tray'] = self.builder.get_object('chk_start_in_tray').get_active()
- new_gtkui_config['enable_appindicator'] = self.builder.get_object('radio_appind').get_active()
- new_gtkui_config['lock_tray'] = self.builder.get_object('chk_lock_tray').get_active()
- passhex = sha(self.builder.get_object('txt_tray_password').get_text()).hexdigest()
+ new_gtkui_config['enable_system_tray'] = self.builder.get_object(
+ 'chk_use_tray'
+ ).get_active()
+ new_gtkui_config['close_to_tray'] = self.builder.get_object(
+ 'chk_min_on_close'
+ ).get_active()
+ new_gtkui_config['start_in_tray'] = self.builder.get_object(
+ 'chk_start_in_tray'
+ ).get_active()
+ new_gtkui_config['enable_appindicator'] = self.builder.get_object(
+ 'radio_appind'
+ ).get_active()
+ new_gtkui_config['lock_tray'] = self.builder.get_object(
+ 'chk_lock_tray'
+ ).get_active()
+ passhex = sha(
+ self.builder.get_object('txt_tray_password').get_text()
+ ).hexdigest()
if passhex != 'c07eb5a8c0dc7bb81c217b67f11c3b7a5e95ffd7':
new_gtkui_config['tray_password'] = passhex
@@ -597,25 +768,33 @@ class Preferences(component.Component):
new_gtkui_config['standalone'] = new_gtkui_standalone
new_gtkui_config['show_rate_in_title'] = self.builder.get_object(
- 'chk_show_rate_in_title',
+ 'chk_show_rate_in_title'
).get_active()
new_gtkui_config['focus_main_window_on_add'] = self.builder.get_object(
- 'chk_focus_main_window_on_add',
+ 'chk_focus_main_window_on_add'
).get_active()
# Other tab #
new_gtkui_config['show_new_releases'] = self.builder.get_object(
- 'chk_show_new_releases',
+ 'chk_show_new_releases'
).get_active()
- new_core_config['send_info'] = self.builder.get_object('chk_send_info').get_active()
- new_core_config['geoip_db_location'] = self.builder.get_object('entry_geoip').get_text()
+ new_core_config['send_info'] = self.builder.get_object(
+ 'chk_send_info'
+ ).get_active()
+ new_core_config['geoip_db_location'] = self.builder.get_object(
+ 'entry_geoip'
+ ).get_text()
# Daemon tab #
- new_core_config['daemon_port'] = self.builder.get_object('spin_daemon_port').get_value_as_int()
+ new_core_config['daemon_port'] = self.builder.get_object(
+ 'spin_daemon_port'
+ ).get_value_as_int()
new_core_config['allow_remote'] = self.builder.get_object(
- 'chk_allow_remote_connections',
+ 'chk_allow_remote_connections'
+ ).get_active()
+ new_core_config['new_release_check'] = self.builder.get_object(
+ 'chk_new_releases'
).get_active()
- new_core_config['new_release_check'] = self.builder.get_object('chk_new_releases').get_active()
# Proxy tab #
new_core_config['proxy'] = {
@@ -624,44 +803,66 @@ class Preferences(component.Component):
'password': self.builder.get_object('entry_proxy_pass').get_text(),
'hostname': self.builder.get_object('entry_proxy_host').get_text(),
'port': self.builder.get_object('spin_proxy_port').get_value_as_int(),
- 'proxy_hostnames': self.builder.get_object('chk_proxy_host_resolve').get_active(),
- 'proxy_peer_connections': self.builder.get_object('chk_proxy_peer_conn').get_active(),
- 'proxy_tracker_connections': self.builder.get_object('chk_proxy_tracker_conn').get_active(),
+ 'proxy_hostnames': self.builder.get_object(
+ 'chk_proxy_host_resolve'
+ ).get_active(),
+ 'proxy_peer_connections': self.builder.get_object(
+ 'chk_proxy_peer_conn'
+ ).get_active(),
+ 'proxy_tracker_connections': self.builder.get_object(
+ 'chk_proxy_tracker_conn'
+ ).get_active(),
'force_proxy': self.builder.get_object('chk_force_proxy').get_active(),
- 'anonymous_mode': self.builder.get_object('chk_anonymous_mode').get_active(),
+ 'anonymous_mode': self.builder.get_object(
+ 'chk_anonymous_mode'
+ ).get_active(),
}
# Queue tab #
- new_core_config['queue_new_to_top'] = self.builder.get_object('chk_queue_new_top').get_active()
+ new_core_config['queue_new_to_top'] = self.builder.get_object(
+ 'chk_queue_new_top'
+ ).get_active()
new_core_config['max_active_seeding'] = self.builder.get_object(
- 'spin_seeding',
+ 'spin_seeding'
).get_value_as_int()
new_core_config['max_active_downloading'] = self.builder.get_object(
- 'spin_downloading',
+ 'spin_downloading'
+ ).get_value_as_int()
+ new_core_config['max_active_limit'] = self.builder.get_object(
+ 'spin_active'
).get_value_as_int()
- new_core_config['max_active_limit'] = self.builder.get_object('spin_active').get_value_as_int()
new_core_config['dont_count_slow_torrents'] = self.builder.get_object(
- 'chk_dont_count_slow_torrents',
+ 'chk_dont_count_slow_torrents'
).get_active()
new_core_config['auto_manage_prefer_seeds'] = self.builder.get_object(
- 'chk_auto_manage_prefer_seeds',
+ 'chk_auto_manage_prefer_seeds'
+ ).get_active()
+ new_core_config['stop_seed_at_ratio'] = self.builder.get_object(
+ 'chk_share_ratio'
).get_active()
- new_core_config['stop_seed_at_ratio'] = self.builder.get_object('chk_share_ratio').get_active()
new_core_config['remove_seed_at_ratio'] = self.builder.get_object(
- 'radio_remove_ratio',
+ 'radio_remove_ratio'
).get_active()
- new_core_config['stop_seed_ratio'] = self.builder.get_object('spin_share_ratio').get_value()
+ new_core_config['stop_seed_ratio'] = self.builder.get_object(
+ 'spin_share_ratio'
+ ).get_value()
new_core_config['share_ratio_limit'] = self.builder.get_object(
- 'spin_share_ratio_limit',
+ 'spin_share_ratio_limit'
).get_value()
new_core_config['seed_time_ratio_limit'] = self.builder.get_object(
- 'spin_seed_time_ratio_limit',
+ 'spin_seed_time_ratio_limit'
+ ).get_value()
+ new_core_config['seed_time_limit'] = self.builder.get_object(
+ 'spin_seed_time_limit'
).get_value()
- new_core_config['seed_time_limit'] = self.builder.get_object('spin_seed_time_limit').get_value()
# Cache tab #
- new_core_config['cache_size'] = self.builder.get_object('spin_cache_size').get_value_as_int()
- new_core_config['cache_expiry'] = self.builder.get_object('spin_cache_expiry').get_value_as_int()
+ new_core_config['cache_size'] = self.builder.get_object(
+ 'spin_cache_size'
+ ).get_value_as_int()
+ new_core_config['cache_expiry'] = self.builder.get_object(
+ 'spin_cache_expiry'
+ ).get_value_as_int()
# Run plugin hook to apply preferences
component.get('PluginManager').run_on_apply_prefs()
@@ -673,8 +874,7 @@ class Preferences(component.Component):
active = self.language_combo.get_active()
if active == -1:
dialog = InformationDialog(
- _('Attention'),
- _('You must choose a language'),
+ _('Attention'), _('You must choose a language')
)
dialog.run()
return
@@ -718,20 +918,26 @@ class Preferences(component.Component):
self.show()
if was_standalone != new_gtkui_standalone:
+
def on_response(response):
if response == gtk.RESPONSE_YES:
- shutdown_daemon = (not client.is_standalone() and
- client.connected() and
- client.is_localhost())
- component.get('MainWindow').quit(shutdown=shutdown_daemon, restart=True)
+ shutdown_daemon = (
+ not client.is_standalone()
+ and client.connected()
+ and client.is_localhost()
+ )
+ component.get('MainWindow').quit(
+ shutdown=shutdown_daemon, restart=True
+ )
else:
self.gtkui_config['standalone'] = not new_gtkui_standalone
self.builder.get_object('radio_standalone').set_active(
- self.gtkui_config['standalone'],
+ self.gtkui_config['standalone']
)
self.builder.get_object('radio_thinclient').set_active(
- not self.gtkui_config['standalone'],
+ not self.gtkui_config['standalone']
)
+
mode = 'Thinclient' if was_standalone else 'Standalone'
dialog = YesNoDialog(
_('Switching Deluge Client Mode...'),
@@ -747,16 +953,20 @@ class Preferences(component.Component):
def __update_cache_status(self):
# Updates the cache status labels with the info in the dict
cache_labels = (
- 'label_cache_read_ops', 'label_cache_write_ops',
- 'label_cache_num_blocks_read', 'label_cache_num_blocks_written',
- 'label_cache_read_hit_ratio', 'label_cache_write_hit_ratio',
- 'label_cache_num_blocks_cache_hits', 'label_cache_disk_blocks_in_use',
+ 'label_cache_read_ops',
+ 'label_cache_write_ops',
+ 'label_cache_num_blocks_read',
+ 'label_cache_num_blocks_written',
+ 'label_cache_read_hit_ratio',
+ 'label_cache_write_hit_ratio',
+ 'label_cache_num_blocks_cache_hits',
+ 'label_cache_disk_blocks_in_use',
'label_cache_read_cache_blocks',
)
for widget_name in cache_labels:
widget = self.builder.get_object(widget_name)
- key = widget_name[len('label_cache_'):]
+ key = widget_name[len('label_cache_') :]
if not widget_name.endswith('ratio'):
key = 'disk.' + key
value = self.cache_status.get(key, 0)
@@ -772,7 +982,9 @@ class Preferences(component.Component):
self.cache_status = status
self.__update_cache_status()
- client.core.get_session_status(DISK_CACHE_KEYS).addCallback(on_get_session_status)
+ client.core.get_session_status(DISK_CACHE_KEYS).addCallback(
+ on_get_session_status
+ )
def on_pref_dialog_delete_event(self, widget, event):
self.hide()
@@ -816,10 +1028,7 @@ class Preferences(component.Component):
'alignment_tray_type': True,
'chk_lock_tray': True,
},
- 'chk_lock_tray': {
- 'txt_tray_password': True,
- 'password_label': True,
- },
+ 'chk_lock_tray': {'txt_tray_password': True, 'password_label': True},
'radio_open_folder_custom': {
'combo_file_manager': False,
'txt_open_folder_location': True,
@@ -887,12 +1096,17 @@ class Preferences(component.Component):
self.builder.get_object('port_img').set_from_stock(gtk.STOCK_YES, 4)
self.builder.get_object('port_img').show()
else:
- self.builder.get_object('port_img').set_from_stock(gtk.STOCK_DIALOG_WARNING, 4)
+ self.builder.get_object('port_img').set_from_stock(
+ gtk.STOCK_DIALOG_WARNING, 4
+ )
self.builder.get_object('port_img').show()
+
client.core.test_listen_port().addCallback(on_get_test)
# XXX: Consider using gtk.Spinner() instead of the loading gif
# It requires gtk.ver > 2.12
- self.builder.get_object('port_img').set_from_file(deluge.common.get_pixmap('loading.gif'))
+ self.builder.get_object('port_img').set_from_file(
+ deluge.common.get_pixmap('loading.gif')
+ )
self.builder.get_object('port_img').show()
client.force_call()
@@ -923,9 +1137,15 @@ class Preferences(component.Component):
plugin_info = component.get('PluginManager').get_plugin_info(name)
self.builder.get_object('label_plugin_author').set_text(plugin_info['Author'])
self.builder.get_object('label_plugin_version').set_text(plugin_info['Version'])
- self.builder.get_object('label_plugin_email').set_text(plugin_info['Author-email'])
- self.builder.get_object('label_plugin_homepage').set_text(plugin_info['Home-page'])
- self.builder.get_object('label_plugin_details').set_text(plugin_info['Description'])
+ self.builder.get_object('label_plugin_email').set_text(
+ plugin_info['Author-email']
+ )
+ self.builder.get_object('label_plugin_homepage').set_text(
+ plugin_info['Home-page']
+ )
+ self.builder.get_object('label_plugin_details').set_text(
+ plugin_info['Description']
+ )
def on_button_plugin_install_clicked(self, widget):
log.debug('on_button_plugin_install_clicked')
@@ -933,7 +1153,12 @@ class Preferences(component.Component):
_('Select the Plugin'),
self.pref_dialog,
gtk.FILE_CHOOSER_ACTION_OPEN,
- 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,
+ ),
)
chooser.set_transient_for(self.pref_dialog)
@@ -956,11 +1181,9 @@ class Preferences(component.Component):
from base64 import b64encode
import shutil
+
filename = os.path.split(filepath)[1]
- shutil.copyfile(
- filepath,
- os.path.join(get_config_dir(), 'plugins', filename),
- )
+ shutil.copyfile(filepath, os.path.join(get_config_dir(), 'plugins', filename))
component.get('PluginManager').scan_for_plugins()
@@ -998,22 +1221,41 @@ class Preferences(component.Component):
def on_combo_proxy_type_changed(self, widget):
proxy_type = self.builder.get_object('combo_proxy_type').get_active()
proxy_entries = [
- 'label_proxy_host', 'entry_proxy_host', 'label_proxy_port', 'spin_proxy_port',
- 'label_proxy_pass', 'entry_proxy_pass', 'label_proxy_user', 'entry_proxy_user',
- 'chk_proxy_host_resolve', 'chk_proxy_peer_conn', 'chk_proxy_tracker_conn',
+ 'label_proxy_host',
+ 'entry_proxy_host',
+ 'label_proxy_port',
+ 'spin_proxy_port',
+ 'label_proxy_pass',
+ 'entry_proxy_pass',
+ 'label_proxy_user',
+ 'entry_proxy_user',
+ 'chk_proxy_host_resolve',
+ 'chk_proxy_peer_conn',
+ 'chk_proxy_tracker_conn',
]
# 0: None, 1: Socks4, 2: Socks5, 3: Socks5 Auth, 4: HTTP, 5: HTTP Auth, 6: I2P
show_entries = []
if proxy_type > 0:
- show_entries.extend([
- 'label_proxy_host', 'entry_proxy_host', 'label_proxy_port', 'spin_proxy_port',
- 'chk_proxy_peer_conn', 'chk_proxy_tracker_conn',
- ])
+ show_entries.extend(
+ [
+ 'label_proxy_host',
+ 'entry_proxy_host',
+ 'label_proxy_port',
+ 'spin_proxy_port',
+ 'chk_proxy_peer_conn',
+ 'chk_proxy_tracker_conn',
+ ]
+ )
if proxy_type in (3, 5):
- show_entries.extend([
- 'label_proxy_pass', 'entry_proxy_pass', 'label_proxy_user', 'entry_proxy_user',
- ])
+ show_entries.extend(
+ [
+ 'label_proxy_pass',
+ 'entry_proxy_pass',
+ 'label_proxy_user',
+ 'entry_proxy_user',
+ ]
+ )
if proxy_type in (2, 3, 4, 5):
show_entries.extend(['chk_proxy_host_resolve'])
@@ -1053,8 +1295,10 @@ class Preferences(component.Component):
ErrorDialog(
_('Server Side Error'),
_('An error occurred on the server'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
+
client.core.get_known_accounts().addCallback(on_ok).addErrback(on_fail)
def on_get_known_accounts(self, known_accounts):
@@ -1072,9 +1316,15 @@ class Preferences(component.Component):
for account in known_accounts:
accounts_iter = self.accounts_liststore.append()
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_USERNAME, account['username'])
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_LEVEL, account['authlevel'])
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_PASSWORD, account['password'])
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_USERNAME, account['username']
+ )
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_LEVEL, account['authlevel']
+ )
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_PASSWORD, account['password']
+ )
def on_accounts_selection_changed(self, treeselection):
log.debug('on_accounts_selection_changed')
@@ -1090,7 +1340,9 @@ class Preferences(component.Component):
self.builder.get_object('accounts_delete').set_sensitive(False)
def on_accounts_add_clicked(self, widget):
- dialog = AccountDialog(levels_mapping=client.auth_levels_mapping, parent=self.pref_dialog)
+ dialog = AccountDialog(
+ levels_mapping=client.auth_levels_mapping, parent=self.pref_dialog
+ )
def dialog_finished(response_id):
username = dialog.get_username()
@@ -1099,28 +1351,36 @@ class Preferences(component.Component):
def add_ok(rv):
accounts_iter = self.accounts_liststore.append()
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_USERNAME, username)
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_LEVEL, authlevel)
- self.accounts_liststore.set_value(accounts_iter, ACCOUNTS_PASSWORD, password)
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_USERNAME, username
+ )
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_LEVEL, authlevel
+ )
+ self.accounts_liststore.set_value(
+ accounts_iter, ACCOUNTS_PASSWORD, password
+ )
def add_fail(failure):
if failure.type == AuthManagerError:
ErrorDialog(
_('Error Adding Account'),
_('Authentication failed'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
else:
ErrorDialog(
_('Error Adding Account'),
_('An error occurred while adding account'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
if response_id == gtk.RESPONSE_OK:
- client.core.create_account(
- username, password, authlevel,
- ).addCallback(add_ok).addErrback(add_fail)
+ client.core.create_account(username, password, authlevel).addCallback(
+ add_ok
+ ).addErrback(add_fail)
dialog.run().addCallback(dialog_finished)
@@ -1138,7 +1398,6 @@ class Preferences(component.Component):
)
def dialog_finished(response_id):
-
def update_ok(rc):
model.set_value(itr, ACCOUNTS_PASSWORD, dialog.get_username())
model.set_value(itr, ACCOUNTS_LEVEL, dialog.get_authlevel())
@@ -1147,14 +1406,13 @@ class Preferences(component.Component):
ErrorDialog(
_('Error Updating Account'),
_('An error occurred while updating account'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
if response_id == gtk.RESPONSE_OK:
client.core.update_account(
- dialog.get_username(),
- dialog.get_password(),
- dialog.get_authlevel(),
+ dialog.get_username(), dialog.get_password(), dialog.get_authlevel()
).addCallback(update_ok).addErrback(update_fail)
dialog.run().addCallback(dialog_finished)
@@ -1166,8 +1424,10 @@ class Preferences(component.Component):
username = model[itr][0]
header = _('Remove Account')
- text = _('Are you sure you want to remove the account with the '
- 'username "%(username)s"?' % {'username': username})
+ text = _(
+ 'Are you sure you want to remove the account with the '
+ 'username "%(username)s"?' % {'username': username}
+ )
dialog = YesNoDialog(header, text, parent=self.pref_dialog)
def dialog_finished(response_id):
@@ -1179,18 +1439,22 @@ class Preferences(component.Component):
ErrorDialog(
_('Error Removing Account'),
_('Auhentication failed'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
else:
ErrorDialog(
_('Error Removing Account'),
_('An error occurred while removing account'),
- parent=self.pref_dialog, details=failure.getErrorMessage(),
+ parent=self.pref_dialog,
+ details=failure.getErrorMessage(),
).run()
+
if response_id == gtk.RESPONSE_YES:
- client.core.remove_account(
- username,
- ).addCallback(remove_ok).addErrback(remove_fail)
+ client.core.remove_account(username).addCallback(remove_ok).addErrback(
+ remove_fail
+ )
+
dialog.run().addCallback(dialog_finished)
def on_piecesbar_toggle_toggled(self, widget):
@@ -1228,21 +1492,35 @@ class Preferences(component.Component):
def __set_color(self, state, from_config=False):
if from_config:
color = Color(*self.gtkui_config['pieces_color_%s' % state])
- log.debug('Setting %r color state from config to %s', state, (color.red, color.green, color.blue))
+ log.debug(
+ 'Setting %r color state from config to %s',
+ state,
+ (color.red, color.green, color.blue),
+ )
self.builder.get_object('%s_color' % state).set_color(color)
else:
color = self.builder.get_object('%s_color' % state).get_color()
- log.debug('Setting %r color state to %s', state, (color.red, color.green, color.blue))
- self.gtkui_config['pieces_color_%s' % state] = [color.red, color.green, color.blue]
+ log.debug(
+ 'Setting %r color state to %s',
+ state,
+ (color.red, color.green, color.blue),
+ )
+ self.gtkui_config['pieces_color_%s' % state] = [
+ color.red,
+ color.green,
+ color.blue,
+ ]
self.gtkui_config.save()
self.gtkui_config.apply_set_functions('pieces_colors')
self.builder.get_object('revert_color_%s' % state).set_sensitive(
- [color.red, color.green, color.blue] != self.COLOR_DEFAULTS[state],
+ [color.red, color.green, color.blue] != self.COLOR_DEFAULTS[state]
)
def __revert_color(self, state, from_config=False):
log.debug('Reverting %r color state', state)
- self.builder.get_object('%s_color' % state).set_color(Color(*self.COLOR_DEFAULTS[state]))
+ self.builder.get_object('%s_color' % state).set_color(
+ Color(*self.COLOR_DEFAULTS[state])
+ )
self.builder.get_object('revert_color_%s' % state).set_sensitive(False)
self.gtkui_config.apply_set_functions('pieces_colors')
diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py
index 9312d1da1..9693dca58 100644
--- a/deluge/ui/gtkui/queuedtorrents.py
+++ b/deluge/ui/gtkui/queuedtorrents.py
@@ -13,7 +13,13 @@ import logging
import os.path
from gobject import timeout_add
-from gtk import STOCK_SORT_DESCENDING, Builder, CellRendererText, ListStore, TreeViewColumn
+from gtk import (
+ STOCK_SORT_DESCENDING,
+ Builder,
+ CellRendererText,
+ ListStore,
+ TreeViewColumn,
+)
import deluge.common
import deluge.component as component
@@ -26,15 +32,19 @@ log = logging.getLogger(__name__)
class QueuedTorrents(component.Component):
def __init__(self):
- component.Component.__init__(self, 'QueuedTorrents', depend=['StatusBar', 'AddTorrentDialog'])
+ component.Component.__init__(
+ self, 'QueuedTorrents', depend=['StatusBar', 'AddTorrentDialog']
+ )
self.queue = []
self.status_item = None
self.config = ConfigManager('gtkui.conf')
self.builder = Builder()
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'queuedtorrents.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'queuedtorrents.ui')
+ )
+ )
self.builder.get_object('chk_autoadd').set_active(self.config['autoadd_queued'])
self.dialog = self.builder.get_object('queued_torrents_dialog')
self.dialog.set_icon(get_logo(32))
@@ -42,7 +52,9 @@ class QueuedTorrents(component.Component):
self.builder.connect_signals(self)
self.treeview = self.builder.get_object('treeview')
- self.treeview.append_column(TreeViewColumn(_('Torrent'), CellRendererText(), text=0))
+ self.treeview.append_column(
+ TreeViewColumn(_('Torrent'), CellRendererText(), text=0)
+ )
self.liststore = ListStore(str, str)
self.treeview.set_model(self.liststore)
diff --git a/deluge/ui/gtkui/removetorrentdialog.py b/deluge/ui/gtkui/removetorrentdialog.py
index c53e20f48..92bbe1e8c 100644
--- a/deluge/ui/gtkui/removetorrentdialog.py
+++ b/deluge/ui/gtkui/removetorrentdialog.py
@@ -32,6 +32,7 @@ class RemoveTorrentDialog(object):
:raises ValueError: if `torrent_id` contains no torrent_ids or is None
"""
+
def __init__(self, torrent_ids, delete_files=False):
if not isinstance(torrent_ids, list) and not isinstance(torrent_ids, tuple):
raise TypeError('requires a list of torrent_ids')
@@ -42,9 +43,11 @@ class RemoveTorrentDialog(object):
self.__torrent_ids = torrent_ids
self.builder = gtk.Builder()
- self.builder.add_from_file(deluge.common.resource_filename(
- 'deluge.ui.gtkui', os.path.join('glade', 'remove_torrent_dialog.ui'),
- ))
+ self.builder.add_from_file(
+ deluge.common.resource_filename(
+ 'deluge.ui.gtkui', os.path.join('glade', 'remove_torrent_dialog.ui')
+ )
+ )
self.__dialog = self.builder.get_object('remove_torrent_dialog')
self.__dialog.set_transient_for(component.get('MainWindow').window)
@@ -55,7 +58,11 @@ class RemoveTorrentDialog(object):
label_torrents = self.builder.get_object('label_torrents')
num_torrents = len(self.__torrent_ids)
if num_torrents == 1:
- label_torrents.set_markup(component.get('TorrentView').get_torrent_status(self.__torrent_ids[0])['name'])
+ label_torrents.set_markup(
+ component.get('TorrentView').get_torrent_status(self.__torrent_ids[0])[
+ 'name'
+ ]
+ )
else:
label_title.set_markup(_('Remove the selected torrents?'))
label_torrents.set_markup(_('Total of %s torrents selected') % num_torrents)
diff --git a/deluge/ui/gtkui/sidebar.py b/deluge/ui/gtkui/sidebar.py
index 103f2ca5a..f4eacfc17 100644
--- a/deluge/ui/gtkui/sidebar.py
+++ b/deluge/ui/gtkui/sidebar.py
@@ -25,6 +25,7 @@ class SideBar(component.Component):
manages the sidebar-tabs.
purpose : plugins
"""
+
def __init__(self):
component.Component.__init__(self, 'SideBar')
main_builder = component.get('MainWindow').get_builder()
diff --git a/deluge/ui/gtkui/status_tab.py b/deluge/ui/gtkui/status_tab.py
index 740a7b0d0..ae2c454c7 100644
--- a/deluge/ui/gtkui/status_tab.py
+++ b/deluge/ui/gtkui/status_tab.py
@@ -15,8 +15,15 @@ import deluge.component as component
from deluge.common import fpeer
from deluge.configmanager import ConfigManager
from deluge.ui.gtkui.piecesbar import PiecesBar
-from deluge.ui.gtkui.tab_data_funcs import (fdate_or_never, fpcnt, fratio, fseed_rank_or_dash, fspeed_max,
- ftime_or_dash, ftotal_sized)
+from deluge.ui.gtkui.tab_data_funcs import (
+ fdate_or_never,
+ fpcnt,
+ fratio,
+ fseed_rank_or_dash,
+ fspeed_max,
+ ftime_or_dash,
+ ftotal_sized,
+)
from deluge.ui.gtkui.torrentdetails import Tab, TabWidget
log = logging.getLogger(__name__)
@@ -33,19 +40,23 @@ class StatusTab(Tab):
self.add_tab_widget('summary_availability', fratio, ('distributed_copies',))
self.add_tab_widget(
- 'summary_total_downloaded', ftotal_sized,
+ 'summary_total_downloaded',
+ ftotal_sized,
('all_time_download', 'total_payload_download'),
)
self.add_tab_widget(
- 'summary_total_uploaded', ftotal_sized,
+ 'summary_total_uploaded',
+ ftotal_sized,
('total_uploaded', 'total_payload_upload'),
)
self.add_tab_widget(
- 'summary_download_speed', fspeed_max,
+ 'summary_download_speed',
+ fspeed_max,
('download_payload_rate', 'max_download_speed'),
)
self.add_tab_widget(
- 'summary_upload_speed', fspeed_max,
+ 'summary_upload_speed',
+ fspeed_max,
('upload_payload_rate', 'max_upload_speed'),
)
self.add_tab_widget('summary_seeds', fpeer, ('num_seeds', 'total_seeds'))
@@ -54,12 +65,20 @@ class StatusTab(Tab):
self.add_tab_widget('summary_share_ratio', fratio, ('ratio',))
self.add_tab_widget('summary_active_time', ftime_or_dash, ('active_time',))
self.add_tab_widget('summary_seed_time', ftime_or_dash, ('seeding_time',))
- self.add_tab_widget('summary_seed_rank', fseed_rank_or_dash, ('seed_rank', 'seeding_time'))
+ self.add_tab_widget(
+ 'summary_seed_rank', fseed_rank_or_dash, ('seed_rank', 'seeding_time')
+ )
self.add_tab_widget('progressbar', fpcnt, ('progress', 'state', 'message'))
- self.add_tab_widget('summary_last_seen_complete', fdate_or_never, ('last_seen_complete',))
- self.add_tab_widget('summary_last_transfer', ftime_or_dash, ('time_since_transfer',))
+ self.add_tab_widget(
+ 'summary_last_seen_complete', fdate_or_never, ('last_seen_complete',)
+ )
+ self.add_tab_widget(
+ 'summary_last_transfer', ftime_or_dash, ('time_since_transfer',)
+ )
- self.config.register_set_function('show_piecesbar', self.on_show_piecesbar_config_changed, apply_now=True)
+ self.config.register_set_function(
+ 'show_piecesbar', self.on_show_piecesbar_config_changed, apply_now=True
+ )
def update(self):
# Get the first selected torrent
@@ -76,7 +95,7 @@ class StatusTab(Tab):
status_keys.extend(['pieces', 'num_pieces'])
component.get('SessionProxy').get_torrent_status(
- selected, status_keys,
+ selected, status_keys
).addCallback(self._on_get_torrent_status)
def _on_get_torrent_status(self, status):
@@ -96,7 +115,10 @@ class StatusTab(Tab):
if self.config['show_piecesbar']:
if self.piecesbar.get_fraction() != fraction:
self.piecesbar.set_fraction(fraction)
- if status['state'] != 'Checking' and self.piecesbar.get_pieces() != status['pieces']:
+ if (
+ status['state'] != 'Checking'
+ and self.piecesbar.get_pieces() != status['pieces']
+ ):
# Skip pieces assignment if checking torrent.
self.piecesbar.set_pieces(status['pieces'], status['num_pieces'])
self.piecesbar.update()
@@ -113,10 +135,12 @@ class StatusTab(Tab):
def show_piecesbar(self):
if self.piecesbar is None:
self.piecesbar = PiecesBar()
- self.main_builder.get_object(
- 'status_progress_vbox',
- ).pack_start(self.piecesbar, False, False, 0)
- self.tab_widgets['piecesbar'] = TabWidget(self.piecesbar, fpcnt, ('progress', 'state', 'message'))
+ self.main_builder.get_object('status_progress_vbox').pack_start(
+ self.piecesbar, False, False, 0
+ )
+ self.tab_widgets['piecesbar'] = TabWidget(
+ self.piecesbar, fpcnt, ('progress', 'state', 'message')
+ )
self.piecesbar.show()
self.progressbar.hide()
diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py
index d9edc9d81..0d50f7571 100644
--- a/deluge/ui/gtkui/statusbar.py
+++ b/deluge/ui/gtkui/statusbar.py
@@ -24,7 +24,15 @@ log = logging.getLogger(__name__)
class StatusBarItem(object):
- def __init__(self, image=None, stock=None, text=None, markup=False, callback=None, tooltip=None):
+ def __init__(
+ self,
+ image=None,
+ stock=None,
+ text=None,
+ markup=False,
+ callback=None,
+ tooltip=None,
+ ):
self._widgets = []
self._ebox = gtk.EventBox()
self._hbox = gtk.HBox()
@@ -137,7 +145,8 @@ class StatusBar(component.Component):
self.statusbar.show_all()
# Create the not connected item
self.not_connected_item = StatusBarItem(
- stock=gtk.STOCK_STOP, text=_('Not Connected'),
+ stock=gtk.STOCK_STOP,
+ text=_('Not Connected'),
callback=self._on_notconnected_item_clicked,
)
# Show the not connected status bar
@@ -146,7 +155,9 @@ class StatusBar(component.Component):
# Hide if necessary
self.visible(self.config['show_statusbar'])
- client.register_event_handler('ConfigValueChangedEvent', self.on_configvaluechanged_event)
+ client.register_event_handler(
+ 'ConfigValueChangedEvent', self.on_configvaluechanged_event
+ )
def start(self):
# Add in images and labels
@@ -155,35 +166,40 @@ class StatusBar(component.Component):
self.connections_item = self.add_item(
stock=gtk.STOCK_NETWORK,
callback=self._on_connection_item_clicked,
- tooltip=_('Connections (Limit)'), pack_start=True,
+ tooltip=_('Connections (Limit)'),
+ pack_start=True,
)
self.download_item = self.add_item(
image=get_pixmap('downloading16.png'),
callback=self._on_download_item_clicked,
- tooltip=_('Download Speed (Limit)'), pack_start=True,
+ tooltip=_('Download Speed (Limit)'),
+ pack_start=True,
)
self.upload_item = self.add_item(
image=get_pixmap('seeding16.png'),
callback=self._on_upload_item_clicked,
- tooltip=_('Upload Speed (Limit)'), pack_start=True,
+ tooltip=_('Upload Speed (Limit)'),
+ pack_start=True,
)
self.traffic_item = self.add_item(
image=get_pixmap('traffic16.png'),
callback=self._on_traffic_item_clicked,
- tooltip=_('Protocol Traffic (Down:Up)'), pack_start=True,
+ tooltip=_('Protocol Traffic (Down:Up)'),
+ pack_start=True,
)
self.dht_item = StatusBarItem(
- image=get_pixmap('dht16.png'), tooltip=_('DHT Nodes'),
+ image=get_pixmap('dht16.png'), tooltip=_('DHT Nodes')
)
self.diskspace_item = self.add_item(
stock=gtk.STOCK_HARDDISK,
callback=self._on_diskspace_item_clicked,
- tooltip=_('Free Disk Space'), pack_start=True,
+ tooltip=_('Free Disk Space'),
+ pack_start=True,
)
self.health_item = self.add_item(
@@ -195,7 +211,7 @@ class StatusBar(component.Component):
)
self.external_ip_item = self.add_item(
- tooltip=_('External IP Address'), pack_start=True,
+ tooltip=_('External IP Address'), pack_start=True
)
self.health = False
@@ -205,11 +221,11 @@ class StatusBar(component.Component):
self._on_max_download_speed(configs['max_download_speed'])
self._on_max_upload_speed(configs['max_upload_speed'])
self._on_dht(configs['dht'])
+
# Get some config values
- client.core.get_config_values([
- 'max_connections_global', 'max_download_speed',
- 'max_upload_speed', 'dht',
- ]).addCallback(update_config_values)
+ client.core.get_config_values(
+ ['max_connections_global', 'max_download_speed', 'max_upload_speed', 'dht']
+ ).addCallback(update_config_values)
def stop(self):
# When stopped, we just show the not connected thingy
@@ -238,7 +254,16 @@ class StatusBar(component.Component):
def show_not_connected(self):
self.hbox.pack_start(self.not_connected_item.get_eventbox(), False, False, 0)
- def add_item(self, image=None, stock=None, text=None, markup=False, callback=None, tooltip=None, pack_start=False):
+ def add_item(
+ self,
+ image=None,
+ stock=None,
+ text=None,
+ markup=False,
+ callback=None,
+ tooltip=None,
+ pack_start=False,
+ ):
"""Adds an item to the status bar"""
# The return tuple.. we return whatever widgets we add
item = StatusBarItem(image, stock, text, markup, callback, tooltip)
@@ -256,7 +281,9 @@ class StatusBar(component.Component):
except Exception as ex:
log.debug('Unable to remove widget: %s', ex)
- def add_timeout_item(self, seconds=3, image=None, stock=None, text=None, callback=None):
+ def add_timeout_item(
+ self, seconds=3, image=None, stock=None, text=None, callback=None
+ ):
"""Adds an item to the StatusBar for seconds"""
item = self.add_item(image, stock, text, callback)
# Start a timer to remove this item in seconds
@@ -266,7 +293,7 @@ class StatusBar(component.Component):
"""Displays a warning to the user in the status bar"""
if text not in self.current_warnings:
item = self.add_item(
- stock=gtk.STOCK_DIALOG_WARNING, text=text, callback=callback,
+ stock=gtk.STOCK_DIALOG_WARNING, text=text, callback=callback
)
self.current_warnings.append(text)
timeout_add(3000, self.remove_warning, item)
@@ -278,11 +305,18 @@ class StatusBar(component.Component):
def clear_statusbar(self):
def remove(child):
self.hbox.remove(child)
+
self.hbox.foreach(remove)
def send_status_request(self):
# Sends an async request for data from the core
- keys = ['num_peers', 'upload_rate', 'download_rate', 'payload_upload_rate', 'payload_download_rate']
+ keys = [
+ 'num_peers',
+ 'upload_rate',
+ 'download_rate',
+ 'payload_upload_rate',
+ 'payload_download_rate',
+ ]
if self.dht_status:
keys.append('dht_nodes')
@@ -315,10 +349,18 @@ class StatusBar(component.Component):
self.remove_item(self.dht_item)
def _on_get_session_status(self, status):
- self.download_rate = fspeed(status['payload_download_rate'], precision=0, shortform=True)
- self.upload_rate = fspeed(status['payload_upload_rate'], precision=0, shortform=True)
- self.download_protocol_rate = (status['download_rate'] - status['payload_download_rate']) // 1024
- self.upload_protocol_rate = (status['upload_rate'] - status['payload_upload_rate']) // 1024
+ self.download_rate = fspeed(
+ status['payload_download_rate'], precision=0, shortform=True
+ )
+ self.upload_rate = fspeed(
+ status['payload_upload_rate'], precision=0, shortform=True
+ )
+ self.download_protocol_rate = (
+ status['download_rate'] - status['payload_download_rate']
+ ) // 1024
+ self.upload_protocol_rate = (
+ status['upload_rate'] - status['payload_upload_rate']
+ ) // 1024
self.num_connections = status['num_peers']
self.update_download_label()
self.update_upload_label()
@@ -336,9 +378,13 @@ class StatusBar(component.Component):
def _on_get_free_space(self, space):
if space >= 0:
- self.diskspace_item.set_markup('<small>%s</small>' % fsize(space, shortform=True))
+ self.diskspace_item.set_markup(
+ '<small>%s</small>' % fsize(space, shortform=True)
+ )
else:
- self.diskspace_item.set_markup('<span foreground="red">' + _('Error') + '</span>')
+ self.diskspace_item.set_markup(
+ '<span foreground="red">' + _('Error') + '</span>'
+ )
def _on_max_download_speed(self, max_download_speed):
self.max_download_speed = max_download_speed
@@ -357,7 +403,10 @@ class StatusBar(component.Component):
if self.max_connections_global < 0:
label_string = '%s' % self.num_connections
else:
- label_string = '%s <small>(%s)</small>' % (self.num_connections, self.max_connections_global)
+ label_string = '%s <small>(%s)</small>' % (
+ self.num_connections,
+ self.max_connections_global,
+ )
self.connections_item.set_markup(label_string)
@@ -371,7 +420,9 @@ class StatusBar(component.Component):
label_string = self.download_rate
else:
label_string = '%s <small>(%i %s)</small>' % (
- self.download_rate, self.max_download_speed, _('K/s'),
+ self.download_rate,
+ self.max_download_speed,
+ _('K/s'),
)
self.download_item.set_markup(label_string)
@@ -382,13 +433,19 @@ class StatusBar(component.Component):
label_string = self.upload_rate
else:
label_string = '%s <small>(%i %s)</small>' % (
- self.upload_rate, self.max_upload_speed, _('K/s'),
+ self.upload_rate,
+ self.max_upload_speed,
+ _('K/s'),
)
self.upload_item.set_markup(label_string)
def update_traffic_label(self):
- label_string = '<small>%i:%i %s</small>' % (self.download_protocol_rate, self.upload_protocol_rate, _('K/s'))
+ label_string = '<small>%i:%i %s</small>' % (
+ self.download_protocol_rate,
+ self.upload_protocol_rate,
+ _('K/s'),
+ )
self.traffic_item.set_markup(label_string)
def update(self):
@@ -398,16 +455,25 @@ class StatusBar(component.Component):
log.debug('_on_set_unlimit_other %s', core_key)
other_dialog_info = {
'max_download_speed': (
- _('Download Speed Limit'), _('Set the maximum download speed'),
- _('K/s'), 'downloading.svg', self.max_download_speed,
+ _('Download Speed Limit'),
+ _('Set the maximum download speed'),
+ _('K/s'),
+ 'downloading.svg',
+ self.max_download_speed,
),
'max_upload_speed': (
- _('Upload Speed Limit'), _('Set the maximum upload speed'),
- _('K/s'), 'seeding.svg', self.max_upload_speed,
+ _('Upload Speed Limit'),
+ _('Set the maximum upload speed'),
+ _('K/s'),
+ 'seeding.svg',
+ self.max_upload_speed,
),
'max_connections_global': (
- _('Incoming Connections'), _('Set the maximum incoming connections'),
- '', gtk.STOCK_NETWORK, self.max_connections_global,
+ _('Incoming Connections'),
+ _('Set the maximum incoming connections'),
+ '',
+ gtk.STOCK_NETWORK,
+ self.max_connections_global,
),
}
@@ -424,9 +490,11 @@ class StatusBar(component.Component):
if widget.get_name() == 'unlimited':
set_value(-1)
elif widget.get_name() == 'other':
+
def dialog_finished(response_id):
if response_id == gtk.RESPONSE_OK:
set_value(dialog.get_value())
+
dialog = dialogs.OtherDialog(*other_dialog_info[core_key])
dialog.run().addCallback(set_value)
else:
@@ -438,7 +506,9 @@ class StatusBar(component.Component):
self.config['tray_download_speed_list'],
self._on_set_download_speed,
self.max_download_speed,
- _('K/s'), show_notset=True, show_other=True,
+ _('K/s'),
+ show_notset=True,
+ show_other=True,
)
menu.show_all()
menu.popup(None, None, None, event.button, event.time)
@@ -452,7 +522,9 @@ class StatusBar(component.Component):
self.config['tray_upload_speed_list'],
self._on_set_upload_speed,
self.max_upload_speed,
- _('K/s'), show_notset=True, show_other=True,
+ _('K/s'),
+ show_notset=True,
+ show_other=True,
)
menu.show_all()
menu.popup(None, None, None, event.button, event.time)
@@ -465,7 +537,9 @@ class StatusBar(component.Component):
menu = common.build_menu_radio_list(
self.config['connection_limit_list'],
self._on_set_connection_limit,
- self.max_connections_global, show_notset=True, show_other=True,
+ self.max_connections_global,
+ show_notset=True,
+ show_other=True,
)
menu.show_all()
menu.popup(None, None, None, event.button, event.time)
diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py
index 878aeb584..f54300304 100644
--- a/deluge/ui/gtkui/systemtray.py
+++ b/deluge/ui/gtkui/systemtray.py
@@ -12,11 +12,22 @@ from __future__ import unicode_literals
import logging
import os
-from gtk import (Builder, RadioMenuItem, status_icon_new_from_icon_name, status_icon_new_from_pixbuf,
- status_icon_position_menu)
+from gtk import (
+ Builder,
+ RadioMenuItem,
+ status_icon_new_from_icon_name,
+ status_icon_new_from_pixbuf,
+ status_icon_position_menu,
+)
import deluge.component as component
-from deluge.common import fspeed, get_pixmap, osx_check, resource_filename, windows_check
+from deluge.common import (
+ fspeed,
+ get_pixmap,
+ osx_check,
+ resource_filename,
+ windows_check,
+)
from deluge.configmanager import ConfigManager
from deluge.ui.client import client
from deluge.ui.gtkui import dialogs
@@ -48,10 +59,14 @@ class SystemTray(component.Component):
'separatormenuitem3',
'separatormenuitem4',
]
- self.config.register_set_function('enable_system_tray', self.on_enable_system_tray_set)
+ self.config.register_set_function(
+ 'enable_system_tray', self.on_enable_system_tray_set
+ )
# bit of a hack to prevent function from doing something on startup
self.__enabled_set_once = False
- self.config.register_set_function('enable_appindicator', self.on_enable_appindicator_set)
+ self.config.register_set_function(
+ 'enable_appindicator', self.on_enable_appindicator_set
+ )
self.max_download_speed = -1.0
self.download_rate = 0.0
@@ -66,10 +81,9 @@ class SystemTray(component.Component):
def enable(self):
"""Enables the system tray icon."""
self.builder = Builder()
- self.builder.add_from_file(resource_filename(
- 'deluge.ui.gtkui',
- os.path.join('glade', 'tray_menu.ui'),
- ))
+ self.builder.add_from_file(
+ resource_filename('deluge.ui.gtkui', os.path.join('glade', 'tray_menu.ui'))
+ )
self.builder.connect_signals(self)
@@ -78,9 +92,7 @@ class SystemTray(component.Component):
if appindicator and self.config['enable_appindicator']:
log.debug('Enabling the Application Indicator...')
self.indicator = appindicator.Indicator(
- 'deluge',
- 'deluge',
- appindicator.CATEGORY_APPLICATION_STATUS,
+ 'deluge', 'deluge', appindicator.CATEGORY_APPLICATION_STATUS
)
try:
self.indicator.set_property('title', _('Deluge'))
@@ -91,8 +103,12 @@ class SystemTray(component.Component):
self.indicator.set_menu(self.tray_menu)
# Make sure the status of the Show Window MenuItem is correct
- self._sig_win_hide = self.mainwindow.window.connect('hide', self._on_window_hide)
- self._sig_win_show = self.mainwindow.window.connect('show', self._on_window_show)
+ self._sig_win_hide = self.mainwindow.window.connect(
+ 'hide', self._on_window_hide
+ )
+ self._sig_win_show = self.mainwindow.window.connect(
+ 'show', self._on_window_show
+ )
if self.mainwindow.visible():
self.builder.get_object('menuitem_show_deluge').set_active(True)
else:
@@ -111,10 +127,16 @@ class SystemTray(component.Component):
self.tray.connect('activate', self.on_tray_clicked)
self.tray.connect('popup-menu', self.on_tray_popup)
- self.builder.get_object('download-limit-image').set_from_file(get_pixmap('downloading16.png'))
- self.builder.get_object('upload-limit-image').set_from_file(get_pixmap('seeding16.png'))
+ self.builder.get_object('download-limit-image').set_from_file(
+ get_pixmap('downloading16.png')
+ )
+ self.builder.get_object('upload-limit-image').set_from_file(
+ get_pixmap('seeding16.png')
+ )
- client.register_event_handler('ConfigValueChangedEvent', self.config_value_changed)
+ client.register_event_handler(
+ 'ConfigValueChangedEvent', self.config_value_changed
+ )
if client.connected():
# We're connected so we need to get some values from the core
self.__start()
@@ -146,7 +168,10 @@ class SystemTray(component.Component):
def update_config_values(configs):
self._on_max_download_speed(configs['max_download_speed'])
self._on_max_upload_speed(configs['max_upload_speed'])
- client.core.get_config_values(['max_download_speed', 'max_upload_speed']).addCallback(update_config_values)
+
+ client.core.get_config_values(
+ ['max_download_speed', 'max_upload_speed']
+ ).addCallback(update_config_values)
def start(self):
self.__start()
@@ -170,10 +195,9 @@ class SystemTray(component.Component):
self.tray.set_visible(False)
def send_status_request(self):
- client.core.get_session_status([
- 'payload_upload_rate',
- 'payload_download_rate',
- ]).addCallback(self._on_get_session_status)
+ client.core.get_session_status(
+ ['payload_upload_rate', 'payload_download_rate']
+ ).addCallback(self._on_get_session_status)
def config_value_changed(self, key, value):
"""This is called when we received a config_value_changed signal from
@@ -221,8 +245,13 @@ class SystemTray(component.Component):
max_upload_speed = '%s %s' % (max_upload_speed, _('K/s'))
msg = '%s\n%s: %s (%s)\n%s: %s (%s)' % (
- _('Deluge'), _('Down'), self.download_rate,
- max_download_speed, _('Up'), self.upload_rate, max_upload_speed,
+ _('Deluge'),
+ _('Down'),
+ self.download_rate,
+ max_download_speed,
+ _('Up'),
+ self.upload_rate,
+ max_upload_speed,
)
# Set the tooltip
@@ -233,24 +262,28 @@ class SystemTray(component.Component):
def build_tray_bwsetsubmenu(self):
# Create the Download speed list sub-menu
submenu_bwdownset = build_menu_radio_list(
- self.config['tray_download_speed_list'], self.on_tray_setbwdown,
+ self.config['tray_download_speed_list'],
+ self.on_tray_setbwdown,
self.max_download_speed,
- _('K/s'), show_notset=True, show_other=True,
+ _('K/s'),
+ show_notset=True,
+ show_other=True,
)
# Create the Upload speed list sub-menu
submenu_bwupset = build_menu_radio_list(
- self.config['tray_upload_speed_list'], self.on_tray_setbwup,
+ self.config['tray_upload_speed_list'],
+ self.on_tray_setbwup,
self.max_upload_speed,
- _('K/s'), show_notset=True, show_other=True,
+ _('K/s'),
+ show_notset=True,
+ show_other=True,
)
# Add the sub-menus to the tray menu
self.builder.get_object('menuitem_download_limit').set_submenu(
- submenu_bwdownset,
- )
- self.builder.get_object('menuitem_upload_limit').set_submenu(
- submenu_bwupset,
+ submenu_bwdownset
)
+ self.builder.get_object('menuitem_upload_limit').set_submenu(submenu_bwupset)
# Show the sub-menus for all to see
submenu_bwdownset.show_all()
@@ -324,7 +357,9 @@ class SystemTray(component.Component):
if windows_check() or osx_check():
popup_function = None
button = 0
- self.tray_menu.popup(None, None, popup_function, button, activate_time, status_icon)
+ self.tray_menu.popup(
+ None, None, popup_function, button, activate_time, status_icon
+ )
def on_menuitem_show_deluge_activate(self, menuitem):
log.debug('on_menuitem_show_deluge_activate')
@@ -359,8 +394,12 @@ class SystemTray(component.Component):
if not widget.get_active():
return
self.setbwlimit(
- widget, _('Download Speed Limit'), _('Set the maximum download speed'),
- 'max_download_speed', 'tray_download_speed_list', self.max_download_speed,
+ widget,
+ _('Download Speed Limit'),
+ _('Set the maximum download speed'),
+ 'max_download_speed',
+ 'tray_download_speed_list',
+ self.max_download_speed,
'downloading.svg',
)
@@ -370,8 +409,12 @@ class SystemTray(component.Component):
if not widget.get_active():
return
self.setbwlimit(
- widget, _('Upload Speed Limit'), _('Set the maximum upload speed'),
- 'max_upload_speed', 'tray_upload_speed_list', self.max_upload_speed,
+ widget,
+ _('Upload Speed Limit'),
+ _('Set the maximum upload speed'),
+ 'max_upload_speed',
+ 'tray_upload_speed_list',
+ self.max_upload_speed,
'seeding.svg',
)
@@ -387,6 +430,7 @@ class SystemTray(component.Component):
def setbwlimit(self, widget, header, text, core_key, ui_key, default, image):
"""Sets the bandwidth limit based on the user selection."""
+
def set_value(value):
log.debug('setbwlimit: %s', value)
if value is None:
diff --git a/deluge/ui/gtkui/toolbar.py b/deluge/ui/gtkui/toolbar.py
index c266806c4..b478e0277 100644
--- a/deluge/ui/gtkui/toolbar.py
+++ b/deluge/ui/gtkui/toolbar.py
@@ -45,7 +45,7 @@ class ToolBar(component.Component):
def start(self):
self.main_builder.get_object('toolbutton_connectionmanager').set_visible(
- not self.config['standalone'],
+ not self.config['standalone']
)
for widget in self.change_sensitivity:
@@ -63,7 +63,9 @@ class ToolBar(component.Component):
self.config['show_toolbar'] = visible
- def add_toolbutton(self, callback, label=None, image=None, stock=None, tooltip=None):
+ def add_toolbutton(
+ self, callback, label=None, image=None, stock=None, tooltip=None
+ ):
"""Adds a toolbutton to the toolbar"""
toolbutton = ToolButton()
if stock is not None:
diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py
index 95544f532..66498c16f 100644
--- a/deluge/ui/gtkui/torrentdetails.py
+++ b/deluge/ui/gtkui/torrentdetails.py
@@ -33,7 +33,9 @@ class Tab(object):
self.weight = -1
self.main_builder = component.get('MainWindow').get_builder()
- self._child_widget = self.main_builder.get_object(child_widget)if child_widget else None
+ self._child_widget = (
+ self.main_builder.get_object(child_widget) if child_widget else None
+ )
self._tab_label = self.main_builder.get_object(tab_label) if tab_label else None
self.tab_widgets = {}
@@ -161,7 +163,10 @@ class TorrentDetails(component.Component):
state = default_order
# We need to rename the tab in the state for backwards compat
- self.state = [(tab_name.replace('Statistics', 'Status'), visible) for tab_name, visible in state]
+ self.state = [
+ (tab_name.replace('Statistics', 'Status'), visible)
+ for tab_name, visible in state
+ ]
for tab in default_tabs.values():
self.add_tab(tab(), generate_menu=False)
@@ -175,8 +180,7 @@ class TorrentDetails(component.Component):
# weights is a list of visible tab names in weight order
weights = sorted(
- (tab.weight, name)
- for name, tab in self.tabs.items() if tab.is_visible
+ (tab.weight, name) for name, tab in self.tabs.items() if tab.is_visible
)
log.debug('weights: %s', weights)
@@ -216,9 +220,7 @@ class TorrentDetails(component.Component):
insert_pos = self.tab_insert_position(weight)
log.debug('Trying to insert tab at %d', insert_pos)
pos = self.notebook.insert_page(
- tab.get_child_widget(),
- tab.get_tab_label(),
- insert_pos,
+ tab.get_child_widget(), tab.get_tab_label(), insert_pos
)
log.debug('Tab inserted at %d', pos)
tab.position = pos
@@ -288,8 +290,10 @@ class TorrentDetails(component.Component):
def show_tab(self, tab_name, generate_menu=True):
log.debug(
- '%s\n%s\n%s', self.tabs[tab_name].get_child_widget(),
- self.tabs[tab_name].get_tab_label(), self.tabs[tab_name].position,
+ '%s\n%s\n%s',
+ self.tabs[tab_name].get_child_widget(),
+ self.tabs[tab_name].get_tab_label(),
+ self.tabs[tab_name].position,
)
position = self.tab_insert_position(self.tabs[tab_name].weight)
@@ -395,7 +399,10 @@ class TorrentDetails(component.Component):
# Get the tab name
name = None
for tab in self.tabs:
- if self.tabs[tab].position == page_num and self.tabs[tab].is_visible:
+ if (
+ self.tabs[tab].position == page_num
+ and self.tabs[tab].is_visible
+ ):
name = tab
except IndexError:
return
diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py
index bc06cd95d..05f246a77 100644
--- a/deluge/ui/gtkui/torrentview.py
+++ b/deluge/ui/gtkui/torrentview.py
@@ -83,11 +83,11 @@ def eta_column_sort(model, iter1, iter2, data):
def seed_peer_column_sort(model, iter1, iter2, data):
- v1 = model[iter1][data] # num seeds/peers
- v3 = model[iter2][data] # num seeds/peers
+ v1 = model[iter1][data] # num seeds/peers
+ v3 = model[iter2][data] # num seeds/peers
if v1 == v3:
- v2 = model[iter1][data + 1] # total seeds/peers
- v4 = model[iter2][data + 1] # total seeds/peers
+ v2 = model[iter1][data + 1] # total seeds/peers
+ v4 = model[iter2][data + 1] # total seeds/peers
return queue_peer_seed_sort_function(v2, v4)
return queue_peer_seed_sort_function(v1, v3)
@@ -234,11 +234,16 @@ class SearchBox(object):
class TorrentView(ListView, component.Component):
"""TorrentView handles the listing of torrents."""
+
def __init__(self):
- component.Component.__init__(self, 'TorrentView', interval=2, depend=['SessionProxy'])
+ component.Component.__init__(
+ self, 'TorrentView', interval=2, depend=['SessionProxy']
+ )
main_builder = component.get('MainWindow').get_builder()
# Call the ListView constructor
- ListView.__init__(self, main_builder.get_object('torrent_view'), 'torrentview.state')
+ ListView.__init__(
+ self, main_builder.get_object('torrent_view'), 'torrentview.state'
+ )
log.debug('TorrentView Init..')
# If we have gotten the state yet
@@ -257,7 +262,9 @@ class TorrentView(ListView, component.Component):
self.add_text_column('torrent_id', hidden=True, unique=True)
self.add_bool_column('dirty', hidden=True)
self.add_func_column(
- '#', funcs.cell_data_queue, [int],
+ '#',
+ funcs.cell_data_queue,
+ [int],
status_field=['queue'],
sort_func=queue_column_sort,
)
@@ -269,23 +276,31 @@ class TorrentView(ListView, component.Component):
default_sort=True,
)
self.add_func_column(
- _('Size'), funcs.cell_data_size,
+ _('Size'),
+ funcs.cell_data_size,
[TYPE_UINT64],
status_field=['total_wanted'],
)
self.add_func_column(
- _('Downloaded'), funcs.cell_data_size,
+ _('Downloaded'),
+ funcs.cell_data_size,
[TYPE_UINT64],
- status_field=['all_time_download'], default=False,
+ status_field=['all_time_download'],
+ default=False,
)
self.add_func_column(
- _('Uploaded'), funcs.cell_data_size,
+ _('Uploaded'),
+ funcs.cell_data_size,
[TYPE_UINT64],
- status_field=['total_uploaded'], default=False,
+ status_field=['total_uploaded'],
+ default=False,
)
self.add_func_column(
- _('Remaining'), funcs.cell_data_size, [TYPE_UINT64],
- status_field=['total_remaining'], default=False,
+ _('Remaining'),
+ funcs.cell_data_size,
+ [TYPE_UINT64],
+ status_field=['total_remaining'],
+ default=False,
)
self.add_progress_column(
_('Progress'),
@@ -295,67 +310,110 @@ class TorrentView(ListView, component.Component):
sort_func=progress_sort,
)
self.add_func_column(
- _('Seeds'), funcs.cell_data_peer, [int, int],
+ _('Seeds'),
+ funcs.cell_data_peer,
+ [int, int],
status_field=['num_seeds', 'total_seeds'],
- sort_func=seed_peer_column_sort, default=False,
+ sort_func=seed_peer_column_sort,
+ default=False,
)
self.add_func_column(
- _('Peers'), funcs.cell_data_peer, [int, int],
+ _('Peers'),
+ funcs.cell_data_peer,
+ [int, int],
status_field=['num_peers', 'total_peers'],
- sort_func=seed_peer_column_sort, default=False,
+ sort_func=seed_peer_column_sort,
+ default=False,
)
self.add_func_column(
- _('Seeds:Peers'), funcs.cell_data_ratio_seeds_peers, [float],
- status_field=['seeds_peers_ratio'], default=False,
+ _('Seeds:Peers'),
+ funcs.cell_data_ratio_seeds_peers,
+ [float],
+ status_field=['seeds_peers_ratio'],
+ default=False,
)
self.add_func_column(
- _('Down Speed'), funcs.cell_data_speed_down, [int],
+ _('Down Speed'),
+ funcs.cell_data_speed_down,
+ [int],
status_field=['download_payload_rate'],
)
self.add_func_column(
- _('Up Speed'), funcs.cell_data_speed_up, [int],
+ _('Up Speed'),
+ funcs.cell_data_speed_up,
+ [int],
status_field=['upload_payload_rate'],
)
self.add_func_column(
- _('Down Limit'), funcs.cell_data_speed_limit_down, [float],
- status_field=['max_download_speed'], default=False,
+ _('Down Limit'),
+ funcs.cell_data_speed_limit_down,
+ [float],
+ status_field=['max_download_speed'],
+ default=False,
)
self.add_func_column(
- _('Up Limit'), funcs.cell_data_speed_limit_up, [float],
- status_field=['max_upload_speed'], default=False,
+ _('Up Limit'),
+ funcs.cell_data_speed_limit_up,
+ [float],
+ status_field=['max_upload_speed'],
+ default=False,
)
self.add_func_column(
- _('ETA'), funcs.cell_data_time, [int],
- status_field=['eta'], sort_func=eta_column_sort,
+ _('ETA'),
+ funcs.cell_data_time,
+ [int],
+ status_field=['eta'],
+ sort_func=eta_column_sort,
)
self.add_func_column(
- _('Ratio'), funcs.cell_data_ratio_ratio, [float],
- status_field=['ratio'], default=False,
+ _('Ratio'),
+ funcs.cell_data_ratio_ratio,
+ [float],
+ status_field=['ratio'],
+ default=False,
)
self.add_func_column(
- _('Avail'), funcs.cell_data_ratio_avail, [float],
- status_field=['distributed_copies'], default=False,
+ _('Avail'),
+ funcs.cell_data_ratio_avail,
+ [float],
+ status_field=['distributed_copies'],
+ default=False,
)
self.add_func_column(
- _('Added'), funcs.cell_data_date_added, [int],
- status_field=['time_added'], default=False,
+ _('Added'),
+ funcs.cell_data_date_added,
+ [int],
+ status_field=['time_added'],
+ default=False,
)
self.add_func_column(
- _('Completed'), funcs.cell_data_date_completed, [int],
- status_field=['completed_time'], default=False,
+ _('Completed'),
+ funcs.cell_data_date_completed,
+ [int],
+ status_field=['completed_time'],
+ default=False,
)
self.add_func_column(
- _('Complete Seen'), funcs.cell_data_date_or_never, [int],
- status_field=['last_seen_complete'], default=False,
+ _('Complete Seen'),
+ funcs.cell_data_date_or_never,
+ [int],
+ status_field=['last_seen_complete'],
+ default=False,
)
self.add_texticon_column(
- _('Tracker'), function=funcs.cell_data_trackericon,
- status_field=['tracker_host', 'tracker_host'], default=False,
+ _('Tracker'),
+ function=funcs.cell_data_trackericon,
+ status_field=['tracker_host', 'tracker_host'],
+ default=False,
+ )
+ self.add_text_column(
+ _('Download Folder'), status_field=['download_location'], default=False
)
- self.add_text_column(_('Download Folder'), status_field=['download_location'], default=False)
self.add_text_column(_('Owner'), status_field=['owner'], default=False)
self.add_bool_column(
- _('Shared'), status_field=['shared'], default=False,
+ _('Shared'),
+ status_field=['shared'],
+ default=False,
tooltip=_('Torrent is shared between other Deluge users or not.'),
)
self.restore_columns_order_from_state()
@@ -395,15 +453,23 @@ class TorrentView(ListView, component.Component):
continue
status_fields.extend(listview_column.status_field)
component.get('SessionProxy').get_torrents_status(
- {}, status_fields,
+ {}, status_fields
).addCallback(self._on_session_state)
- client.register_event_handler('TorrentStateChangedEvent', self.on_torrentstatechanged_event)
+ client.register_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrentstatechanged_event
+ )
client.register_event_handler('TorrentAddedEvent', self.on_torrentadded_event)
- client.register_event_handler('TorrentRemovedEvent', self.on_torrentremoved_event)
+ client.register_event_handler(
+ 'TorrentRemovedEvent', self.on_torrentremoved_event
+ )
client.register_event_handler('SessionPausedEvent', self.on_sessionpaused_event)
- client.register_event_handler('SessionResumedEvent', self.on_sessionresumed_event)
- client.register_event_handler('TorrentQueueChangedEvent', self.on_torrentqueuechanged_event)
+ client.register_event_handler(
+ 'SessionResumedEvent', self.on_sessionresumed_event
+ )
+ client.register_event_handler(
+ 'TorrentQueueChangedEvent', self.on_torrentqueuechanged_event
+ )
def _on_session_state(self, state):
self.add_rows(state)
@@ -416,12 +482,22 @@ class TorrentView(ListView, component.Component):
def stop(self):
"""Stops the torrentview"""
- client.deregister_event_handler('TorrentStateChangedEvent', self.on_torrentstatechanged_event)
+ client.deregister_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrentstatechanged_event
+ )
client.deregister_event_handler('TorrentAddedEvent', self.on_torrentadded_event)
- client.deregister_event_handler('TorrentRemovedEvent', self.on_torrentremoved_event)
- client.deregister_event_handler('SessionPausedEvent', self.on_sessionpaused_event)
- client.deregister_event_handler('SessionResumedEvent', self.on_sessionresumed_event)
- client.deregister_event_handler('TorrentQueueChangedEvent', self.on_torrentqueuechanged_event)
+ client.deregister_event_handler(
+ 'TorrentRemovedEvent', self.on_torrentremoved_event
+ )
+ client.deregister_event_handler(
+ 'SessionPausedEvent', self.on_sessionpaused_event
+ )
+ client.deregister_event_handler(
+ 'SessionResumedEvent', self.on_sessionresumed_event
+ )
+ client.deregister_event_handler(
+ 'TorrentQueueChangedEvent', self.on_torrentqueuechanged_event
+ )
if self.treeview.get_selection():
self.treeview.get_selection().unselect_all()
@@ -501,9 +577,11 @@ class TorrentView(ListView, component.Component):
# Request the statuses for all these torrent_ids, this is async so we
# will deal with the return in a signal callback.
- d = component.get('SessionProxy').get_torrents_status(
- self.filter, status_keys,
- ).addCallback(self._on_get_torrents_status)
+ d = (
+ component.get('SessionProxy')
+ .get_torrents_status(self.filter, status_keys)
+ .addCallback(self._on_get_torrents_status)
+ )
if select_row:
d.addCallback(self.select_first_row)
@@ -527,7 +605,10 @@ class TorrentView(ListView, component.Component):
"""
if self.got_state:
- if self.search_box.search_pending is not None and self.search_box.search_pending.active():
+ if (
+ self.search_box.search_pending is not None
+ and self.search_box.search_pending.active()
+ ):
# An update request is scheduled, let's wait for that one
return
# Send a status request
@@ -616,7 +697,15 @@ class TorrentView(ListView, component.Component):
for torrent_id in torrent_ids:
# Insert a new row to the liststore
row = self.liststore.append()
- self.liststore.set(row, torrent_id_column, torrent_id, dirty_column, True, filter_column, True)
+ self.liststore.set(
+ row,
+ torrent_id_column,
+ torrent_id,
+ dirty_column,
+ True,
+ filter_column,
+ True,
+ )
def remove_row(self, torrent_id):
"""Removes a row with torrent_id"""
@@ -629,7 +718,10 @@ class TorrentView(ListView, component.Component):
def mark_dirty(self, torrent_id=None):
for row in self.liststore:
- if not torrent_id or row[self.columns['torrent_id'].column_indices[0]] == torrent_id:
+ if (
+ not torrent_id
+ or row[self.columns['torrent_id'].column_indices[0]] == torrent_id
+ ):
# log.debug('marking %s dirty', torrent_id)
row[self.columns['dirty'].column_indices[0]] = True
if torrent_id:
@@ -660,11 +752,19 @@ class TorrentView(ListView, component.Component):
log.debug('Unable to get iter from path: %s', ex)
continue
- child_row = self.treeview.get_model().convert_iter_to_child_iter(None, row)
- child_row = self.treeview.get_model().get_model().convert_iter_to_child_iter(child_row)
+ child_row = self.treeview.get_model().convert_iter_to_child_iter(
+ None, row
+ )
+ child_row = (
+ self.treeview.get_model()
+ .get_model()
+ .convert_iter_to_child_iter(child_row)
+ )
if self.liststore.iter_is_valid(child_row):
try:
- value = self.liststore.get_value(child_row, self.columns['torrent_id'].column_indices[0])
+ value = self.liststore.get_value(
+ child_row, self.columns['torrent_id'].column_indices[0]
+ )
except Exception as ex:
log.debug('Unable to get value from row: %s', ex)
else:
@@ -699,8 +799,12 @@ class TorrentView(ListView, component.Component):
row = self.model_filter.get_iter(path[0])
if self.get_selected_torrents():
- if (self.model_filter.get_value(row, self.columns['torrent_id'].column_indices[0])
- not in self.get_selected_torrents()):
+ if (
+ self.model_filter.get_value(
+ row, self.columns['torrent_id'].column_indices[0]
+ )
+ not in self.get_selected_torrents()
+ ):
self.treeview.get_selection().unselect_all()
self.treeview.get_selection().select_iter(row)
else:
@@ -718,7 +822,9 @@ class TorrentView(ListView, component.Component):
def on_drag_drop(self, widget, drag_context, x, y, timestamp):
widget.stop_emission('drag-drop')
- def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, timestamp):
+ def on_drag_data_received(
+ self, widget, drag_context, x, y, selection_data, info, timestamp
+ ):
widget.stop_emission('drag_data_received')
def on_columns_changed_event(self, treeview):
@@ -750,7 +856,10 @@ class TorrentView(ListView, component.Component):
if self.filter.get('state', None) is not None:
# We have a filter set, let's see if theres anything to hide
# and remove from status
- if torrent_id in self.status and self.status[torrent_id]['state'] != state:
+ if (
+ torrent_id in self.status
+ and self.status[torrent_id]['state'] != state
+ ):
row[self.columns['filter'].column_indices[0]] = False
del self.status[torrent_id]
diff --git a/deluge/ui/gtkui/torrentview_data_funcs.py b/deluge/ui/gtkui/torrentview_data_funcs.py
index 4e3260c0d..db57355be 100644
--- a/deluge/ui/gtkui/torrentview_data_funcs.py
+++ b/deluge/ui/gtkui/torrentview_data_funcs.py
@@ -14,8 +14,16 @@ from functools import partial
import deluge.common as common
import deluge.component as component
-from deluge.ui.gtkui.common import (create_blank_pixbuf, get_pixbuf_at_size, icon_alert, icon_checking,
- icon_downloading, icon_inactive, icon_queued, icon_seeding)
+from deluge.ui.gtkui.common import (
+ create_blank_pixbuf,
+ get_pixbuf_at_size,
+ icon_alert,
+ icon_checking,
+ icon_downloading,
+ icon_inactive,
+ icon_queued,
+ icon_seeding,
+)
# Holds the info for which status icon to display based on TORRENT_STATE
ICON_STATE = {
@@ -155,6 +163,7 @@ def cell_data_speed(cell, model, row, data, cache_key):
except AttributeError:
print('AttributeError')
import traceback
+
traceback.print_exc()
if func_last_value[cache_key] == speed:
return
@@ -162,7 +171,9 @@ def cell_data_speed(cell, model, row, data, cache_key):
if speed > 0:
speed_str = common.fspeed(speed, shortform=True)
- cell.set_property('markup', '{0} <small>{1}</small>'.format(*tuple(speed_str.split())))
+ cell.set_property(
+ 'markup', '{0} <small>{1}</small>'.format(*tuple(speed_str.split()))
+ )
else:
cell.set_property('text', '')
@@ -187,7 +198,9 @@ def cell_data_speed_limit(cell, model, row, data, cache_key):
if speed > 0:
speed_str = common.fspeed(speed * 1024, shortform=True)
- cell.set_property('markup', '{0} <small>{1}</small>'.format(*tuple(speed_str.split())))
+ cell.set_property(
+ 'markup', '{0} <small>{1}</small>'.format(*tuple(speed_str.split()))
+ )
else:
cell.set_property('text', '')
@@ -237,7 +250,9 @@ def cell_data_ratio(cell, model, row, data, cache_key):
if func_last_value[cache_key] == ratio:
return
func_last_value[cache_key] = ratio
- cell.set_property('text', '∞' if ratio < 0 else ('%.1f' % ratio).rstrip('0').rstrip('.'))
+ cell.set_property(
+ 'text', '∞' if ratio < 0 else ('%.1f' % ratio).rstrip('0').rstrip('.')
+ )
def cell_data_ratio_seeds_peers(column, cell, model, row, data):
diff --git a/deluge/ui/gtkui/trackers_tab.py b/deluge/ui/gtkui/trackers_tab.py
index 48677b536..55999761b 100644
--- a/deluge/ui/gtkui/trackers_tab.py
+++ b/deluge/ui/gtkui/trackers_tab.py
@@ -21,7 +21,9 @@ log = logging.getLogger(__name__)
class TrackersTab(Tab):
def __init__(self):
- super(TrackersTab, self).__init__('Trackers', 'trackers_tab', 'trackers_tab_label')
+ super(TrackersTab, self).__init__(
+ 'Trackers', 'trackers_tab', 'trackers_tab_label'
+ )
self.add_tab_widget('summary_next_announce', ftime, ('next_announce',))
self.add_tab_widget('summary_tracker', None, ('tracker_host',))
@@ -43,7 +45,9 @@ class TrackersTab(Tab):
return
session = component.get('SessionProxy')
- session.get_torrent_status(selected, self.status_keys).addCallback(self._on_get_torrent_status)
+ session.get_torrent_status(selected, self.status_keys).addCallback(
+ self._on_get_torrent_status
+ )
def _on_get_torrent_status(self, status):
# Check to see if we got valid data from the core
@@ -64,5 +68,6 @@ class TrackersTab(Tab):
torrent_id = component.get('TorrentView').get_selected_torrent()
if torrent_id:
from deluge.ui.gtkui.edittrackersdialog import EditTrackersDialog
+
dialog = EditTrackersDialog(torrent_id, component.get('MainWindow').window)
dialog.run()
diff --git a/deluge/ui/hostlist.py b/deluge/ui/hostlist.py
index 10d7063b5..ee4c7df7c 100644
--- a/deluge/ui/hostlist.py
+++ b/deluge/ui/hostlist.py
@@ -89,9 +89,15 @@ def migrate_config_2_to_3(config):
class HostList(object):
"""This class contains methods for adding, removing and looking up hosts in hostlist.conf."""
+
def __init__(self):
migrate_hostlist('hostlist.conf.1.2', 'hostlist.conf')
- self.config = Config('hostlist.conf', default_hostlist(), config_dir=get_config_dir(), file_version=3)
+ self.config = Config(
+ 'hostlist.conf',
+ default_hostlist(),
+ config_dir=get_config_dir(),
+ file_version=3,
+ )
self.config.run_converter((1, 2), 3, migrate_config_2_to_3)
self.config.save()
@@ -109,7 +115,11 @@ class HostList(object):
"""
for host_entry in self.config['hosts']:
- if (hostname, port, username) == (host_entry[1], host_entry[2], host_entry[3]):
+ if (hostname, port, username) == (
+ host_entry[1],
+ host_entry[2],
+ host_entry[3],
+ ):
if skip_host_id is not None and skip_host_id == host_entry[0]:
continue
raise ValueError('Host details already in hostlist')
@@ -126,8 +136,10 @@ class HostList(object):
Returns:
str: The new host id.
"""
- if (not password and not username or username == 'localclient') and hostname in LOCALHOST:
- username, password = get_localhost_auth()
+ if (
+ not password and not username or username == 'localclient'
+ ) and hostname in LOCALHOST:
+ username, password = get_localhost_auth()
validate_host_info(hostname, port)
self.check_info_exists(hostname, port, username)
@@ -175,6 +187,7 @@ class HostList(object):
def on_connect(result, c, host_id):
"""Successfully connected to a daemon"""
+
def on_info(info, c):
c.disconnect()
return host_id, 'Online', info
@@ -202,7 +215,11 @@ class HostList(object):
log.error('Error resolving host %s to ip: %s', host, ex.args[1])
return status_offline
- host_conn_info = (ip, port, 'localclient' if not user and host in LOCALHOST else user)
+ host_conn_info = (
+ ip,
+ port,
+ 'localclient' if not user and host in LOCALHOST else user,
+ )
if client.connected() and host_conn_info == client.connection_info():
# Currently connected to host_id daemon.
def on_info(info, host_id):
@@ -232,7 +249,9 @@ class HostList(object):
validate_host_info(hostname, port)
self.check_info_exists(hostname, port, username, skip_host_id=host_id)
- if (not password and not username or username == 'localclient') and hostname in LOCALHOST:
+ if (
+ not password and not username or username == 'localclient'
+ ) and hostname in LOCALHOST:
username, password = get_localhost_auth()
for idx, host_entry in enumerate(self.config['hosts']):
diff --git a/deluge/ui/sessionproxy.py b/deluge/ui/sessionproxy.py
index 8c363b478..5af8e79cd 100644
--- a/deluge/ui/sessionproxy.py
+++ b/deluge/ui/sessionproxy.py
@@ -28,6 +28,7 @@ class SessionProxy(component.Component):
and will try to satisfy client requests from the cache.
"""
+
def __init__(self):
log.debug('SessionProxy init..')
component.Component.__init__(self, 'SessionProxy', interval=5)
@@ -43,7 +44,9 @@ class SessionProxy(component.Component):
self.cache_times = {}
def start(self):
- client.register_event_handler('TorrentStateChangedEvent', self.on_torrent_state_changed)
+ client.register_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrent_state_changed
+ )
client.register_event_handler('TorrentRemovedEvent', self.on_torrent_removed)
client.register_event_handler('TorrentAddedEvent', self.on_torrent_added)
@@ -54,10 +57,13 @@ class SessionProxy(component.Component):
self.torrents.setdefault(torrent_id, [time(), {}])
self.cache_times.setdefault(torrent_id, {})
return torrent_ids
+
return client.core.get_session_state().addCallback(on_get_session_state)
def stop(self):
- client.deregister_event_handler('TorrentStateChangedEvent', self.on_torrent_state_changed)
+ client.deregister_event_handler(
+ 'TorrentStateChangedEvent', self.on_torrent_state_changed
+ )
client.deregister_event_handler('TorrentRemovedEvent', self.on_torrent_removed)
client.deregister_event_handler('TorrentAddedEvent', self.on_torrent_added)
self.torrents = {}
@@ -77,7 +83,9 @@ class SessionProxy(component.Component):
"""
sd = {}
keys = set(keys)
- keys_len = -1 # The number of keys for the current cache (not the len of keys_diff_cached)
+ keys_len = (
+ -1
+ ) # The number of keys for the current cache (not the len of keys_diff_cached)
keys_diff_cached = []
for torrent_id in torrent_ids:
@@ -128,12 +136,13 @@ class SessionProxy(component.Component):
keys = list(self.torrents[torrent_id][1])
for key in keys:
- if time() - self.cache_times[torrent_id].get(key, 0.0) > self.cache_time:
+ if (
+ time() - self.cache_times[torrent_id].get(key, 0.0)
+ > self.cache_time
+ ):
keys_to_get.append(key)
if not keys_to_get:
- return succeed(
- self.create_status_dict([torrent_id], keys)[torrent_id],
- )
+ return succeed(self.create_status_dict([torrent_id], keys)[torrent_id])
else:
d = client.core.get_torrent_status(torrent_id, keys_to_get, True)
@@ -144,6 +153,7 @@ class SessionProxy(component.Component):
for key in keys_to_get:
self.cache_times[torrent_id][key] = t
return self.create_status_dict([torrent_id], keys)[torrent_id]
+
return d.addCallback(on_status, torrent_id)
else:
d = client.core.get_torrent_status(torrent_id, keys, True)
@@ -157,6 +167,7 @@ class SessionProxy(component.Component):
self.cache_times[torrent_id][key] = t
return result
+
return d.addCallback(on_status)
def get_torrents_status(self, filter_dict, keys):
@@ -206,11 +217,15 @@ class SessionProxy(component.Component):
else:
# We need to check if a key is expired
for key in keys:
- if t - self.cache_times[torrent_id].get(key, 0.0) > self.cache_time:
+ if (
+ t - self.cache_times[torrent_id].get(key, 0.0)
+ > self.cache_time
+ ):
to_fetch.append(torrent_id)
break
return to_fetch
+
# -----------------------------------------------------------------------
if not filter_dict:
@@ -254,6 +269,7 @@ class SessionProxy(component.Component):
t = time()
for key in status:
self.cache_times[torrent_id][key] = t
+
client.core.get_torrent_status(torrent_id, []).addCallback(on_status)
def on_torrent_removed(self, torrent_id):
diff --git a/deluge/ui/tracker_icons.py b/deluge/ui/tracker_icons.py
index 492d96d23..48c742f77 100644
--- a/deluge/ui/tracker_icons.py
+++ b/deluge/ui/tracker_icons.py
@@ -36,6 +36,7 @@ except ImportError:
PIL_INSTALLED = False
else:
import deluge.ui.Win32IconImagePlugin # NOQA pylint: disable=unused-import, ungrouped-imports
+
PIL_INSTALLED = True
log = logging.getLogger(__name__)
@@ -45,6 +46,7 @@ class TrackerIcon(object):
"""
Represents a tracker's icon
"""
+
def __init__(self, filename):
"""
Initialises a new TrackerIcon object
@@ -66,9 +68,11 @@ class TrackerIcon(object):
:returns: whether or not they're equal
:rtype: boolean
"""
- return (os.path.samefile(self.filename, other.filename) or
- self.get_mimetype() == other.get_mimetype() and
- self.get_data() == other.get_data())
+ return (
+ os.path.samefile(self.filename, other.filename)
+ or self.get_mimetype() == other.get_mimetype()
+ and self.get_data() == other.get_data()
+ )
def get_mimetype(self):
"""
@@ -122,6 +126,7 @@ class TrackerIcons(Component):
"""
A TrackerIcon factory class
"""
+
def __init__(self, icon_dir=None, no_icon=None):
"""
Initialises a new TrackerIcons object
@@ -209,18 +214,20 @@ class TrackerIcons(Component):
# Start callback chain
d = self.download_page(host)
d.addCallbacks(
- self.on_download_page_complete, self.on_download_page_fail,
+ self.on_download_page_complete,
+ self.on_download_page_fail,
errbackArgs=(host,),
)
d.addCallback(self.parse_html_page)
d.addCallbacks(
- self.on_parse_complete, self.on_parse_fail,
- callbackArgs=(host,),
+ self.on_parse_complete, self.on_parse_fail, callbackArgs=(host,)
)
d.addCallback(self.download_icon, host)
d.addCallbacks(
- self.on_download_icon_complete, self.on_download_icon_fail,
- callbackArgs=(host,), errbackArgs=(host,),
+ self.on_download_icon_complete,
+ self.on_download_icon_fail,
+ callbackArgs=(host,),
+ errbackArgs=(host,),
)
if PIL_INSTALLED:
d.addCallback(self.resize_icon)
@@ -279,7 +286,8 @@ class TrackerIcons(Component):
self.redirects[host] = url_to_host(location)
d = self.download_page(host, url=location)
d.addCallbacks(
- self.on_download_page_complete, self.on_download_page_fail,
+ self.on_download_page_complete,
+ self.on_download_page_fail,
errbackArgs=(host,),
)
@@ -354,7 +362,8 @@ class TrackerIcons(Component):
raise NoIconsError('empty icons list')
(url, mimetype) = icons.pop(0)
d = download_file(
- url, os.path.join(self.dir, host_to_icon_name(host, mimetype)),
+ url,
+ os.path.join(self.dir, host_to_icon_name(host, mimetype)),
force_filename=True,
)
d.addCallback(self.check_icon_is_valid)
@@ -421,25 +430,36 @@ class TrackerIcons(Component):
if f.check(PageRedirect):
# Handle redirect errors
location = urljoin(self.host_to_url(host), error_msg.split(' to ')[1])
- d = self.download_icon([(location, extension_to_mimetype(location.rpartition('.')[2]))] + icons, host)
+ d = self.download_icon(
+ [(location, extension_to_mimetype(location.rpartition('.')[2]))]
+ + icons,
+ host,
+ )
if not icons:
d.addCallbacks(
- self.on_download_icon_complete, self.on_download_icon_fail,
- callbackArgs=(host,), errbackArgs=(host,),
+ self.on_download_icon_complete,
+ self.on_download_icon_fail,
+ callbackArgs=(host,),
+ errbackArgs=(host,),
)
elif f.check(NoResource, ForbiddenResource) and icons:
d = self.download_icon(icons, host)
elif f.check(NoIconsError):
# No icons, try favicon.ico as an act of desperation
d = self.download_icon(
- [(
- urljoin(self.host_to_url(host), 'favicon.ico'),
- extension_to_mimetype('ico'),
- )], host,
+ [
+ (
+ urljoin(self.host_to_url(host), 'favicon.ico'),
+ extension_to_mimetype('ico'),
+ )
+ ],
+ host,
)
d.addCallbacks(
- self.on_download_icon_complete, self.on_download_icon_fail,
- callbackArgs=(host,), errbackArgs=(host,),
+ self.on_download_icon_complete,
+ self.on_download_icon_fail,
+ callbackArgs=(host,),
+ errbackArgs=(host,),
)
else:
# No icons :(
@@ -501,6 +521,7 @@ class TrackerIcons(Component):
host = self.redirects[host]
return 'http://%s/' % host
+
# ------- HELPER CLASSES ------
@@ -508,13 +529,18 @@ class FaviconParser(HTMLParser):
"""
A HTMLParser which extracts favicons from a HTML page
"""
+
def __init__(self):
self.icons = []
self.left_head = False
HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
- if tag == 'link' and ('rel', 'icon') in attrs or ('rel', 'shortcut icon') in attrs:
+ if (
+ tag == 'link'
+ and ('rel', 'icon') in attrs
+ or ('rel', 'shortcut icon') in attrs
+ ):
href = None
icon_type = None
for attr, value in attrs:
@@ -548,6 +574,7 @@ class FaviconParser(HTMLParser):
# ------ HELPER FUNCTIONS ------
+
def url_to_host(url):
"""
Given a URL, returns the host it belongs to
@@ -626,6 +653,7 @@ def extension_to_mimetype(extension):
"""
return MIME_MAP[extension.lower()]
+
# ------ EXCEPTIONS ------
diff --git a/deluge/ui/translations_util.py b/deluge/ui/translations_util.py
index cdffc3230..cd0aac88d 100644
--- a/deluge/ui/translations_util.py
+++ b/deluge/ui/translations_util.py
@@ -20,15 +20,20 @@ from six.moves import builtins
import deluge.common
log = logging.getLogger(__name__)
-log.addHandler(logging.NullHandler()) # Silence: No handlers could be found for logger "deluge.util.lang"
+log.addHandler(
+ logging.NullHandler()
+) # Silence: No handlers could be found for logger "deluge.util.lang"
def set_dummy_trans(warn_msg=None):
-
def _func(*txt):
if warn_msg:
- log.warning('"%s" has been marked for translation, but translation is unavailable.', txt[0])
+ log.warning(
+ '"%s" has been marked for translation, but translation is unavailable.',
+ txt[0],
+ )
return txt[0]
+
builtins.__dict__['_'] = _func
builtins.__dict__['ngettext'] = builtins.__dict__['_n'] = _func
@@ -77,7 +82,9 @@ def set_language(lang):
translations_path = get_translations_path()
try:
- ro = gettext.translation('deluge', localedir=translations_path, languages=[lang])
+ ro = gettext.translation(
+ 'deluge', localedir=translations_path, languages=[lang]
+ )
ro.install()
except IOError as ex:
log.warning('IOError when loading translations: %s', ex)
@@ -95,13 +102,16 @@ def setup_translations(setup_gettext=True, setup_pygtk=False):
if deluge.common.windows_check():
import ctypes
+
try:
libintl = ctypes.cdll.intl
except WindowsError:
# Fallback to named dll.
libintl = ctypes.cdll.LoadLibrary('libintl-8.dll')
- libintl.bindtextdomain(domain, translations_path.encode(sys.getfilesystemencoding()))
+ libintl.bindtextdomain(
+ domain, translations_path.encode(sys.getfilesystemencoding())
+ )
libintl.textdomain(domain)
libintl.bind_textdomain_codeset(domain, 'UTF-8')
libintl.gettext.restype = ctypes.c_char_p
@@ -109,6 +119,7 @@ def setup_translations(setup_gettext=True, setup_pygtk=False):
# Use glade for plugins that still uses it
import gtk
import gtk.glade
+
gtk.glade.bindtextdomain(domain, translations_path)
gtk.glade.textdomain(domain)
except Exception as ex:
diff --git a/deluge/ui/ui.py b/deluge/ui/ui.py
index c1bd16483..6b149f72d 100644
--- a/deluge/ui/ui.py
+++ b/deluge/ui/ui.py
@@ -22,6 +22,7 @@ log = logging.getLogger(__name__)
try:
from setproctitle import setproctitle
except ImportError:
+
def setproctitle(title):
return
@@ -31,6 +32,7 @@ class UI(object):
Base class for UI implementations.
"""
+
cmd_description = """Override with command description"""
def __init__(self, name, **kwargs):
diff --git a/deluge/ui/ui_entry.py b/deluge/ui/ui_entry.py
index 8ce79e14d..b20be980b 100644
--- a/deluge/ui/ui_entry.py
+++ b/deluge/ui/ui_entry.py
@@ -26,9 +26,7 @@ import deluge.configmanager
from deluge.ui.baseargparser import BaseArgParser
from deluge.ui.translations_util import setup_translations
-DEFAULT_PREFS = {
- 'default_ui': 'gtk',
-}
+DEFAULT_PREFS = {'default_ui': 'gtk'}
AMBIGUOUS_CMD_ARGS = ('-h', '--help', '-v', '-V', '--version')
@@ -52,7 +50,10 @@ def start_ui():
"""Function to enable reuse of UI Options group"""
group = _parser.add_argument_group(_('UI Options'))
group.add_argument(
- '-s', '--set-default-ui', dest='default_ui', choices=ui_titles,
+ '-s',
+ '--set-default-ui',
+ dest='default_ui',
+ choices=ui_titles,
help=_('Set the default UI to be run, when no UI is specified'),
)
return _parser
@@ -84,12 +85,15 @@ def start_ui():
# Create subparser for each registered UI. Empty title is used to remove unwanted positional text.
subparsers = parser.add_subparsers(
- dest='selected_ui', metavar='{%s} [UI args]' % ','.join(ui_titles), title=None,
+ dest='selected_ui',
+ metavar='{%s} [UI args]' % ','.join(ui_titles),
+ title=None,
help=_('Alternative UI to launch, with optional ui args \n (default UI: *)'),
)
for ui in ui_titles:
parser_ui = subparsers.add_parser(
- ui, common_help=False,
+ ui,
+ common_help=False,
help=getattr(ui_entrypoints[ui], 'cmd_description', ''),
)
parser_ui.add_argument('ui_args', nargs=argparse.REMAINDER)
@@ -110,21 +114,26 @@ def start_ui():
sys.argv.remove(selected_ui)
try:
- ui = ui_entrypoints[selected_ui](prog='%s %s' % (os.path.basename(sys.argv[0]), selected_ui), ui_args=ui_args)
+ ui = ui_entrypoints[selected_ui](
+ prog='%s %s' % (os.path.basename(sys.argv[0]), selected_ui), ui_args=ui_args
+ )
except KeyError as ex:
log.error(
'Unable to find chosen UI: "%s". Please choose a different UI '
- 'or use "--set-default-ui" to change default UI.', selected_ui,
+ 'or use "--set-default-ui" to change default UI.',
+ selected_ui,
)
except ImportError as ex:
import traceback
+
error_type, error_value, tb = sys.exc_info()
stack = traceback.extract_tb(tb)
last_frame = stack[-1]
if last_frame[0] == __file__:
log.error(
'Unable to find chosen UI: "%s". Please choose a different UI '
- 'or use "--set-default-ui" to change default UI.', selected_ui,
+ 'or use "--set-default-ui" to change default UI.',
+ selected_ui,
)
else:
log.exception(ex)
diff --git a/deluge/ui/web/auth.py b/deluge/ui/web/auth.py
index 4ee526cbe..aefd879e6 100644
--- a/deluge/ui/web/auth.py
+++ b/deluge/ui/web/auth.py
@@ -103,8 +103,10 @@ class Auth(JSONComponent):
checksum = str(make_checksum(session_id))
request.addCookie(
- b'_session_id', session_id + checksum,
- path=request.base + 'json', expires=expires_str,
+ b'_session_id',
+ session_id + checksum,
+ path=request.base + 'json',
+ expires=expires_str,
)
log.debug('Creating session for %s', login)
@@ -144,6 +146,7 @@ class Auth(JSONComponent):
# We are using the 1.1 webui auth method
log.debug('Received a password via the 1.1 auth method')
from base64 import b64decode
+
m = hashlib.md5()
m.update(b64decode(config['old_pwd_salt']))
m.update(password.encode('utf8'))
@@ -200,8 +203,10 @@ class Auth(JSONComponent):
_session_id = request.getCookie('_session_id')
request.addCookie(
- b'_session_id', _session_id,
- path=request.base + b'json', expires=expires_str,
+ b'_session_id',
+ _session_id,
+ path=request.base + b'json',
+ expires=expires_str,
)
if method:
diff --git a/deluge/ui/web/common.py b/deluge/ui/web/common.py
index ee4f3cde5..0935e2f57 100644
--- a/deluge/ui/web/common.py
+++ b/deluge/ui/web/common.py
@@ -33,7 +33,9 @@ def escape(text):
def compress(contents, request):
request.setHeader(b'content-encoding', b'gzip')
- compress_zlib = zlib.compressobj(6, zlib.DEFLATED, zlib.MAX_WBITS + 16, zlib.DEF_MEM_LEVEL, 0)
+ compress_zlib = zlib.compressobj(
+ 6, zlib.DEFLATED, zlib.MAX_WBITS + 16, zlib.DEF_MEM_LEVEL, 0
+ )
contents = compress_zlib.compress(contents)
contents += compress_zlib.flush()
return contents
@@ -49,25 +51,19 @@ try:
A template that adds some built-ins to the rendering
"""
- builtins = {
- '_': _,
- 'escape': escape,
- 'version': common.get_version(),
- }
+ builtins = {'_': _, 'escape': escape, 'version': common.get_version()}
def render(self, *args, **data):
data.update(self.builtins)
rendered = MakoTemplate.render_unicode(self, *args, **data)
return rendered.encode('utf-8')
+
+
except ImportError:
import warnings
- warnings.warn(
- 'The Mako library is required to run deluge.ui.web',
- RuntimeWarning,
- )
+
+ warnings.warn('The Mako library is required to run deluge.ui.web', RuntimeWarning)
class Template(object):
def __new__(cls, *args, **kwargs):
- raise RuntimeError(
- 'The Mako library is required to run deluge.ui.web',
- )
+ raise RuntimeError('The Mako library is required to run deluge.ui.web')
diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py
index 28ce22e0c..4ae84bb4c 100644
--- a/deluge/ui/web/json_api.py
+++ b/deluge/ui/web/json_api.py
@@ -55,6 +55,7 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
:type auth_level: int
"""
+
def wrap(func, *args, **kwargs):
func._json_export = True
func._json_auth_level = auth_level
@@ -95,9 +96,11 @@ class JSON(resource.Resource, component.Component):
Returns:
t.i.d.Deferred: A deferred returning the available remote methods
"""
+
def on_get_methods(methods):
self._remote_methods = methods
return methods
+
return client.daemon.get_method_list().addCallback(on_get_methods)
def _exec_local(self, method, params, request):
@@ -144,7 +147,9 @@ class JSON(resource.Resource, component.Component):
request_id = request_data['id']
except KeyError as ex:
message = 'Invalid JSON request, missing param %s in %s' % (
- ex, request_data)
+ ex,
+ request_data,
+ )
raise JSONException(message)
result = None
@@ -178,7 +183,10 @@ class JSON(resource.Resource, component.Component):
Handles any failures that occurred while making an rpc call.
"""
log.error(reason)
- response['error'] = {'message': '%s: %s' % (reason.__class__.__name__, str(reason)), 'code': 4}
+ response['error'] = {
+ 'message': '%s: %s' % (reason.__class__.__name__, str(reason)),
+ 'code': 4,
+ }
return self._send_response(request, response)
def _on_json_request(self, request):
@@ -187,7 +195,9 @@ class JSON(resource.Resource, component.Component):
_handle_request method for further processing.
"""
if request.getHeader(b'content-type') != b'application/json':
- message = 'Invalid JSON request content-type: %s' % request.getHeader('content-type')
+ message = 'Invalid JSON request content-type: %s' % request.getHeader(
+ 'content-type'
+ )
raise JSONException(message)
log.debug('json-request: %s', request.json)
@@ -208,7 +218,8 @@ class JSON(resource.Resource, component.Component):
"""
log.error(reason)
response = {
- 'result': None, 'id': None,
+ 'result': None,
+ 'id': None,
'error': {
'code': 5,
'message': '%s: %s' % (reason.__class__.__name__, str(reason)),
@@ -355,13 +366,8 @@ class WebApi(JSONComponent):
the web interface. The complete web json interface also exposes all the
methods available from the core RPC.
"""
- XSS_VULN_KEYS = [
- 'name',
- 'message',
- 'comment',
- 'tracker_status',
- 'peers',
- ]
+
+ XSS_VULN_KEYS = ['name', 'message', 'comment', 'tracker_status', 'peers']
def __init__(self):
super(WebApi, self).__init__('Web', depend=['SessionProxy'])
@@ -374,8 +380,12 @@ class WebApi(JSONComponent):
self.sessionproxy = SessionProxy()
def disable(self):
- client.deregister_event_handler('PluginEnabledEvent', self._json.get_remote_methods)
- client.deregister_event_handler('PluginDisabledEvent', self._json.get_remote_methods)
+ client.deregister_event_handler(
+ 'PluginEnabledEvent', self._json.get_remote_methods
+ )
+ client.deregister_event_handler(
+ 'PluginDisabledEvent', self._json.get_remote_methods
+ )
if client.is_standalone():
component.get('Web.PluginManager').stop()
@@ -384,8 +394,12 @@ class WebApi(JSONComponent):
client.set_disconnect_callback(None)
def enable(self):
- client.register_event_handler('PluginEnabledEvent', self._json.get_remote_methods)
- client.register_event_handler('PluginDisabledEvent', self._json.get_remote_methods)
+ client.register_event_handler(
+ 'PluginEnabledEvent', self._json.get_remote_methods
+ )
+ client.register_event_handler(
+ 'PluginDisabledEvent', self._json.get_remote_methods
+ )
if client.is_standalone():
component.get('Web.PluginManager').start()
@@ -452,6 +466,7 @@ class WebApi(JSONComponent):
def on_disconnect(reason):
return str(reason)
+
d.addCallback(on_disconnect)
return d
@@ -487,10 +502,16 @@ class WebApi(JSONComponent):
ui_info['stats']['num_connections'] = stats['num_peers']
ui_info['stats']['upload_rate'] = stats['payload_upload_rate']
ui_info['stats']['download_rate'] = stats['payload_download_rate']
- ui_info['stats']['download_protocol_rate'] = stats['download_rate'] - stats['payload_download_rate']
- ui_info['stats']['upload_protocol_rate'] = stats['upload_rate'] - stats['payload_upload_rate']
+ ui_info['stats']['download_protocol_rate'] = (
+ stats['download_rate'] - stats['payload_download_rate']
+ )
+ ui_info['stats']['upload_protocol_rate'] = (
+ stats['upload_rate'] - stats['payload_upload_rate']
+ )
ui_info['stats']['dht_nodes'] = stats['dht_nodes']
- ui_info['stats']['has_incoming_connections'] = stats['has_incoming_connections']
+ ui_info['stats']['has_incoming_connections'] = stats[
+ 'has_incoming_connections'
+ ]
def got_filters(filters):
ui_info['filters'] = filters
@@ -513,15 +534,17 @@ class WebApi(JSONComponent):
d2 = client.core.get_filter_tree()
d2.addCallback(got_filters)
- d3 = client.core.get_session_status([
- 'num_peers',
- 'payload_download_rate',
- 'payload_upload_rate',
- 'download_rate',
- 'upload_rate',
- 'dht_nodes',
- 'has_incoming_connections',
- ])
+ d3 = client.core.get_session_status(
+ [
+ 'num_peers',
+ 'payload_download_rate',
+ 'payload_upload_rate',
+ 'download_rate',
+ 'upload_rate',
+ 'dht_nodes',
+ 'has_incoming_connections',
+ ]
+ )
d3.addCallback(got_stats)
d4 = client.core.get_free_space(self.core_config.get('download_location'))
@@ -697,7 +720,8 @@ class WebApi(JSONComponent):
if is_magnet(torrent['path']):
log.info(
'Adding torrent from magnet uri `%s` with options `%r`',
- torrent['path'], torrent['options'],
+ torrent['path'],
+ torrent['options'],
)
d = client.core.add_torrent_magnet(torrent['path'], torrent['options'])
deferreds.append(d)
@@ -707,9 +731,12 @@ class WebApi(JSONComponent):
fdump = b64encode(_file.read())
log.info(
'Adding torrent from file `%s` with options `%r`',
- filename, torrent['options'],
+ filename,
+ torrent['options'],
+ )
+ d = client.core.add_torrent_file_async(
+ filename, fdump, torrent['options']
)
- d = client.core.add_torrent_file_async(filename, fdump, torrent['options'])
deferreds.append(d)
return DeferredList(deferreds, consumeErrors=False)
@@ -742,6 +769,7 @@ class WebApi(JSONComponent):
:type host_id: string
"""
+
def response(result):
return result
@@ -820,12 +848,13 @@ class WebApi(JSONComponent):
return main_deferred
try:
+
def on_connect(connected, c):
if not connected:
main_deferred.callback((False, _('Daemon not running')))
return
c.daemon.shutdown()
- main_deferred.callback((True, ))
+ main_deferred.callback((True,))
def on_connect_failed(reason):
main_deferred.callback((False, reason))
@@ -951,6 +980,7 @@ class WebUtils(JSONComponent):
"""
Utility functions for the webui that do not fit in the WebApi.
"""
+
def __init__(self):
super(WebUtils, self).__init__('WebUtils')
diff --git a/deluge/ui/web/pluginmanager.py b/deluge/ui/web/pluginmanager.py
index fe5f0bf25..24f20ce94 100644
--- a/deluge/ui/web/pluginmanager.py
+++ b/deluge/ui/web/pluginmanager.py
@@ -43,8 +43,12 @@ class PluginManager(PluginManagerBase, component.Component):
self.config = ConfigManager('web.conf')
PluginManagerBase.__init__(self, 'web.conf', 'deluge.plugin.web')
- client.register_event_handler('PluginEnabledEvent', self._on_plugin_enabled_event)
- client.register_event_handler('PluginDisabledEvent', self._on_plugin_disabled_event)
+ client.register_event_handler(
+ 'PluginEnabledEvent', self._on_plugin_enabled_event
+ )
+ client.register_event_handler(
+ 'PluginDisabledEvent', self._on_plugin_disabled_event
+ )
def _on_get_enabled_plugins(self, plugins):
for plugin in plugins:
@@ -61,18 +65,26 @@ class PluginManager(PluginManagerBase, component.Component):
try:
plugin = component.get('WebPlugin.' + name)
except KeyError:
- log.debug('%s plugin contains no WebUI code, ignoring WebUI disable call.', name)
+ log.debug(
+ '%s plugin contains no WebUI code, ignoring WebUI disable call.', name
+ )
return
info = gather_info(plugin)
scripts = component.get('Scripts')
for script in info['scripts']:
- scripts.remove_script('%s/%s' % (name.lower(), os.path.basename(script).lower()))
+ scripts.remove_script(
+ '%s/%s' % (name.lower(), os.path.basename(script).lower())
+ )
for script in info['debug_scripts']:
- scripts.remove_script('%s/%s' % (name.lower(), os.path.basename(script).lower()), 'debug')
- scripts.remove_script('%s/%s' % (name.lower(), os.path.basename(script).lower()), 'dev')
+ scripts.remove_script(
+ '%s/%s' % (name.lower(), os.path.basename(script).lower()), 'debug'
+ )
+ scripts.remove_script(
+ '%s/%s' % (name.lower(), os.path.basename(script).lower()), 'dev'
+ )
super(PluginManager, self).disable_plugin(name)
@@ -83,7 +95,9 @@ class PluginManager(PluginManagerBase, component.Component):
try:
plugin = component.get('WebPlugin.' + name)
except KeyError:
- log.info('%s plugin contains no WebUI code, ignoring WebUI enable call.', name)
+ log.info(
+ '%s plugin contains no WebUI code, ignoring WebUI enable call.', name
+ )
return
info = gather_info(plugin)
@@ -91,12 +105,18 @@ class PluginManager(PluginManagerBase, component.Component):
scripts = component.get('Scripts')
for script in info['scripts']:
log.debug('adding script %s for %s', name, os.path.basename(script))
- scripts.add_script('%s/%s' % (name.lower(), os.path.basename(script)), script)
+ scripts.add_script(
+ '%s/%s' % (name.lower(), os.path.basename(script)), script
+ )
for script in info['debug_scripts']:
log.debug('adding debug script %s for %s', name, os.path.basename(script))
- scripts.add_script('%s/%s' % (name.lower(), os.path.basename(script)), script, 'debug')
- scripts.add_script('%s/%s' % (name.lower(), os.path.basename(script)), script, 'dev')
+ scripts.add_script(
+ '%s/%s' % (name.lower(), os.path.basename(script)), script, 'debug'
+ )
+ scripts.add_script(
+ '%s/%s' % (name.lower(), os.path.basename(script)), script, 'dev'
+ )
def start(self):
"""
@@ -111,8 +131,12 @@ class PluginManager(PluginManagerBase, component.Component):
Stop the plugin manager
"""
self.disable_plugins()
- client.deregister_event_handler('PluginEnabledEvent', self._on_plugin_enabled_event)
- client.deregister_event_handler('PluginDisabledEvent', self._on_plugin_disabled_event)
+ client.deregister_event_handler(
+ 'PluginEnabledEvent', self._on_plugin_enabled_event
+ )
+ client.deregister_event_handler(
+ 'PluginDisabledEvent', self._on_plugin_disabled_event
+ )
def update(self):
pass
@@ -126,7 +150,12 @@ class PluginManager(PluginManagerBase, component.Component):
return
info = gather_info(plugin)
info['name'] = name
- info['scripts'] = ['js/%s/%s' % (name.lower(), os.path.basename(s)) for s in info['scripts']]
- info['debug_scripts'] = ['js/%s/%s' % (name.lower(), os.path.basename(s)) for s in info['debug_scripts']]
+ info['scripts'] = [
+ 'js/%s/%s' % (name.lower(), os.path.basename(s)) for s in info['scripts']
+ ]
+ info['debug_scripts'] = [
+ 'js/%s/%s' % (name.lower(), os.path.basename(s))
+ for s in info['debug_scripts']
+ ]
del info['script_directories']
return info
diff --git a/deluge/ui/web/server.py b/deluge/ui/web/server.py
index 62691e335..cfcf92b2e 100644
--- a/deluge/ui/web/server.py
+++ b/deluge/ui/web/server.py
@@ -37,13 +37,11 @@ CONFIG_DEFAULTS = {
# Misc Settings
'enabled_plugins': [],
'default_daemon': '',
-
# Auth Settings
'pwd_salt': 'c26ab3bbd8b137f99cd83c2c1c0963bcc1a35cad',
'pwd_sha1': '2ce1a410bcdcc53064129b6d950f2e9fee4edc1e',
'session_timeout': 3600,
'sessions': {},
-
# UI Settings
'sidebar_show_zero': False,
'sidebar_multiple_filters': True,
@@ -52,7 +50,6 @@ CONFIG_DEFAULTS = {
'theme': 'gray',
'first_login': True,
'language': '',
-
# Server Settings
'base': '/',
'interface': '0.0.0.0',
@@ -63,8 +60,12 @@ CONFIG_DEFAULTS = {
}
UI_CONFIG_KEYS = (
- 'theme', 'sidebar_show_zero', 'sidebar_multiple_filters',
- 'show_session_speed', 'base', 'first_login',
+ 'theme',
+ 'sidebar_show_zero',
+ 'sidebar_multiple_filters',
+ 'show_session_speed',
+ 'base',
+ 'first_login',
)
@@ -89,6 +90,7 @@ class MockGetText(resource.Resource):
It will be used to define the `_` (underscore) function for translations,
and will return the string to translate, as is.
"""
+
def render(self, request):
request.setHeader(b'content-type', b'text/javascript; encoding=utf-8')
data = b'function _(string) { return string; }'
@@ -114,10 +116,7 @@ class Upload(resource.Resource):
print(request.args)
if b'file' not in request.args:
request.setResponseCode(http.OK)
- return json.dumps({
- 'success': True,
- 'files': [],
- })
+ return json.dumps({'success': True, 'files': []})
tempdir = tempfile.mkdtemp(prefix='delugeweb-')
log.debug('uploading files to %s', tempdir)
@@ -132,12 +131,7 @@ class Upload(resource.Resource):
request.setHeader(b'content-type', b'text/html')
request.setResponseCode(http.OK)
- return compress(
- json.dumps({
- 'success': True,
- 'files': filenames,
- }), request,
- )
+ return compress(json.dumps({'success': True, 'files': filenames}), request)
class Render(resource.Resource):
@@ -170,7 +164,6 @@ class Render(resource.Resource):
class Tracker(resource.Resource):
-
def __init__(self):
resource.Resource.__init__(self)
try:
@@ -185,8 +178,7 @@ class Tracker(resource.Resource):
def on_got_icon(self, icon, request):
if icon:
request.setHeader(
- b'cache-control',
- b'public, must-revalidate, max-age=86400',
+ b'cache-control', b'public, must-revalidate, max-age=86400'
)
request.setHeader(b'content-type', icon.get_mimetype().encode('utf8'))
request.setResponseCode(http.OK)
@@ -212,8 +204,7 @@ class Flag(resource.Resource):
filename = common.resource_filename('deluge', os.path.join(*path))
if os.path.exists(filename):
request.setHeader(
- b'cache-control',
- b'public, must-revalidate, max-age=86400',
+ b'cache-control', b'public, must-revalidate, max-age=86400'
)
request.setHeader(b'content-type', b'image/png')
with open(filename, 'rb') as _file:
@@ -226,7 +217,6 @@ class Flag(resource.Resource):
class LookupResource(resource.Resource, component.Component):
-
def __init__(self, name, *directories):
resource.Resource.__init__(self)
component.Component.__init__(self, name)
@@ -274,13 +264,16 @@ class LookupResource(resource.Resource, component.Component):
class ScriptResource(resource.Resource, component.Component):
-
def __init__(self):
resource.Resource.__init__(self)
component.Component.__init__(self, 'Scripts')
self.__scripts = {}
for script_type in ['normal', 'debug', 'dev']:
- self.__scripts[script_type] = {'scripts': {}, 'order': [], 'files_exist': True}
+ self.__scripts[script_type] = {
+ 'scripts': {},
+ 'order': [],
+ 'files_exist': True,
+ }
def has_script_type_files(self, script_type):
"""Returns whether all the script files exist for this script type.
@@ -385,9 +378,15 @@ class ScriptResource(resource.Resource, component.Component):
# Ensure sub-directory scripts are top of list with root directory scripts bottom.
if dirnames:
- scripts.extend(['js/' + os.path.basename(root) + '/' + f for f in files])
+ scripts.extend(
+ ['js/' + os.path.basename(root) + '/' + f for f in files]
+ )
else:
- dirpath = os.path.basename(os.path.dirname(root)) + '/' + os.path.basename(root)
+ dirpath = (
+ os.path.basename(os.path.dirname(root))
+ + '/'
+ + os.path.basename(root)
+ )
for filename in reversed(files):
scripts.insert(script_idx, 'js/' + dirpath + '/' + filename)
@@ -417,7 +416,7 @@ class ScriptResource(resource.Resource, component.Component):
if isinstance(filepath, tuple):
filepath = filepath[0]
- path = filepath + lookup_path[len(pattern):]
+ path = filepath + lookup_path[len(pattern) :]
if not os.path.isfile(path):
continue
@@ -453,7 +452,8 @@ class TopLevel(resource.Resource):
else:
log.warning(
'Cannot find "gettext.js" translation file!'
- ' Text will only be available in English.')
+ ' Text will only be available in English.'
+ )
self.putChild(b'gettext.js', MockGetText())
self.putChild(b'flag', Flag())
self.putChild(b'icons', LookupResource('Icons', rpath('icons')))
@@ -462,16 +462,32 @@ class TopLevel(resource.Resource):
js = ScriptResource()
# configure the dev scripts
- js.add_script('ext-base-debug.js', rpath('js', 'extjs', 'ext-base-debug.js'), 'dev')
- js.add_script('ext-all-debug.js', rpath('js', 'extjs', 'ext-all-debug.js'), 'dev')
- js.add_script_folder('ext-extensions', rpath('js', 'extjs', 'ext-extensions'), 'dev')
+ js.add_script(
+ 'ext-base-debug.js', rpath('js', 'extjs', 'ext-base-debug.js'), 'dev'
+ )
+ js.add_script(
+ 'ext-all-debug.js', rpath('js', 'extjs', 'ext-all-debug.js'), 'dev'
+ )
+ js.add_script_folder(
+ 'ext-extensions', rpath('js', 'extjs', 'ext-extensions'), 'dev'
+ )
js.add_script_folder('deluge-all', rpath('js', 'deluge-all'), 'dev')
# configure the debug scripts
- js.add_script('ext-base-debug.js', rpath('js', 'extjs', 'ext-base-debug.js'), 'debug')
- js.add_script('ext-all-debug.js', rpath('js', 'extjs', 'ext-all-debug.js'), 'debug')
- js.add_script('ext-extensions-debug.js', rpath('js', 'extjs', 'ext-extensions-debug.js'), 'debug')
- js.add_script('deluge-all-debug.js', rpath('js', 'deluge-all-debug.js'), 'debug')
+ js.add_script(
+ 'ext-base-debug.js', rpath('js', 'extjs', 'ext-base-debug.js'), 'debug'
+ )
+ js.add_script(
+ 'ext-all-debug.js', rpath('js', 'extjs', 'ext-all-debug.js'), 'debug'
+ )
+ js.add_script(
+ 'ext-extensions-debug.js',
+ rpath('js', 'extjs', 'ext-extensions-debug.js'),
+ 'debug',
+ )
+ js.add_script(
+ 'deluge-all-debug.js', rpath('js', 'deluge-all-debug.js'), 'debug'
+ )
# configure the normal scripts
js.add_script('ext-base.js', rpath('js', 'extjs', 'ext-base.js'))
@@ -558,9 +574,14 @@ class TopLevel(resource.Resource):
if not self.js.has_script_type_files(script_type):
if not dev_ver:
- log.warning('Failed to enable WebUI "%s" mode, script files are missing!', script_type)
+ log.warning(
+ 'Failed to enable WebUI "%s" mode, script files are missing!',
+ script_type,
+ )
# Fallback to checking other types in order and selecting first with files available.
- for alt_script_type in [x for x in ['normal', 'debug', 'dev'] if x != script_type]:
+ for alt_script_type in [
+ x for x in ['normal', 'debug', 'dev'] if x != script_type
+ ]:
if self.js.has_script_type_files(alt_script_type):
script_type = alt_script_type
if not dev_ver:
@@ -588,7 +609,6 @@ class TopLevel(resource.Resource):
class DelugeWeb(component.Component):
-
def __init__(self, options=None, daemon=True):
"""
Setup the DelugeWeb server.
@@ -600,7 +620,9 @@ class DelugeWeb(component.Component):
"""
component.Component.__init__(self, 'DelugeWeb', depend=['Web'])
- self.config = configmanager.ConfigManager('web.conf', defaults=CONFIG_DEFAULTS, file_version=2)
+ self.config = configmanager.ConfigManager(
+ 'web.conf', defaults=CONFIG_DEFAULTS, file_version=2
+ )
self.config.run_converter((0, 1), 2, self._migrate_config_1_to_2)
self.config.register_set_function('language', self._on_language_changed)
self.socket = None
@@ -614,7 +636,9 @@ class DelugeWeb(component.Component):
self.base = self.config['base']
if options:
- self.interface = options.interface if options.interface is not None else self.interface
+ self.interface = (
+ options.interface if options.interface is not None else self.interface
+ )
self.port = options.port if options.port else self.port
self.base = options.base if options.base else self.base
if options.ssl:
@@ -624,8 +648,7 @@ class DelugeWeb(component.Component):
if self.base != '/':
# Strip away slashes and serve on the base path as well as root path
- self.top_level.putChild(
- self.base.strip('/'), self.top_level)
+ self.top_level.putChild(self.base.strip('/'), self.top_level)
setup_translations(setup_gettext=True, setup_pygtk=False)
@@ -657,10 +680,10 @@ class DelugeWeb(component.Component):
def win_handler(ctrl_type):
log.debug('ctrl type: %s', ctrl_type)
- if ctrl_type == CTRL_CLOSE_EVENT or \
- ctrl_type == CTRL_SHUTDOWN_EVENT:
+ if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
self.shutdown()
return 1
+
SetConsoleCtrlHandler(win_handler)
def start(self):
@@ -699,7 +722,7 @@ class DelugeWeb(component.Component):
self.port,
self.site,
get_context_factory(cert, pkey),
- interface=self.interface
+ interface=self.interface,
)
ip = self.socket.getHost().host
ip = '[%s]' % ip if is_ipv6(ip) else ip
diff --git a/deluge/ui/web/web.py b/deluge/ui/web/web.py
index 8d1e12794..4d0624791 100644
--- a/deluge/ui/web/web.py
+++ b/deluge/ui/web/web.py
@@ -24,24 +24,42 @@ class Web(UI):
cmd_description = """Web-based user interface (http://localhost:8112)"""
def __init__(self, *args, **kwargs):
- super(Web, self).__init__('web', *args, description='Starts the Deluge Web interface', **kwargs)
+ super(Web, self).__init__(
+ 'web', *args, description='Starts the Deluge Web interface', **kwargs
+ )
self.__server = None
group = self.parser.add_argument_group(_('Web Server Options'))
group.add_argument(
- '-i', '--interface', metavar='<ip_address>', action='store',
+ '-i',
+ '--interface',
+ metavar='<ip_address>',
+ action='store',
help=_('IP address for web server to listen on'),
)
group.add_argument(
- '-p', '--port', metavar='<port>', type=int, action='store',
+ '-p',
+ '--port',
+ metavar='<port>',
+ type=int,
+ action='store',
help=_('Port for web server to listen on'),
)
group.add_argument(
- '-b', '--base', metavar='<path>', action='store',
+ '-b',
+ '--base',
+ metavar='<path>',
+ action='store',
help=_('Set the base path that the ui is running on'),
)
- group.add_argument('--ssl', action='store_true', help=_('Force the web server to use SSL'))
- group.add_argument('--no-ssl', action='store_true', help=_('Force the web server to disable SSL'))
+ group.add_argument(
+ '--ssl', action='store_true', help=_('Force the web server to use SSL')
+ )
+ group.add_argument(
+ '--no-ssl',
+ action='store_true',
+ help=_('Force the web server to disable SSL'),
+ )
self.parser.add_process_arg_group()
@property
@@ -52,6 +70,7 @@ class Web(UI):
super(Web, self).start()
from deluge.ui.web import server
+
self.__server = server.DelugeWeb(options=self.options)
def run():
@@ -59,8 +78,14 @@ class Web(UI):
self.server.install_signal_handlers()
self.server.start()
except CannotListenError as ex:
- log.error('%s \nCheck that deluge-web or webui plugin is not already running.', ex)
+ log.error(
+ '%s \nCheck that deluge-web or webui plugin is not already running.',
+ ex,
+ )
except Exception as ex:
log.exception(ex)
raise
- run_profiled(run, output_file=self.options.profile, do_profile=self.options.profile)
+
+ run_profiled(
+ run, output_file=self.options.profile, do_profile=self.options.profile
+ )
diff --git a/docs/source/conf.py b/docs/source/conf.py
index bed14d95c..76f4a0fbc 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -29,7 +29,13 @@ __builtin__.__dict__['_n'] = lambda s, p, n: s if n == 1 else p
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
-sys.path.append(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.path.pardir), os.path.pardir)))
+sys.path.append(
+ os.path.abspath(
+ os.path.join(
+ os.path.join(os.path.dirname(__file__), os.path.pardir), os.path.pardir
+ )
+ )
+)
class Mock(object):
@@ -58,11 +64,25 @@ class Mock(object):
MOCK_MODULES = [
- 'deluge.ui.gtkui.gtkui', 'deluge._libtorrent',
- 'libtorrent', 'psyco',
- 'pygtk', 'gtk', 'gobject', 'gtk.gdk', 'pango', 'cairo', 'pangocairo',
- 'curses', 'win32api', 'win32file', 'win32process', 'win32pipe',
- 'pywintypes', 'win32con', 'win32event',
+ 'deluge.ui.gtkui.gtkui',
+ 'deluge._libtorrent',
+ 'libtorrent',
+ 'psyco',
+ 'pygtk',
+ 'gtk',
+ 'gobject',
+ 'gtk.gdk',
+ 'pango',
+ 'cairo',
+ 'pangocairo',
+ 'curses',
+ 'win32api',
+ 'win32file',
+ 'win32process',
+ 'win32pipe',
+ 'pywintypes',
+ 'win32con',
+ 'win32event',
]
for mod_name in MOCK_MODULES:
@@ -218,8 +238,7 @@ htmlhelp_basename = 'delugedoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
- ('index', 'deluge.tex', 'deluge Documentation',
- 'Deluge Team', 'manual'),
+ ('index', 'deluge.tex', 'deluge Documentation', 'Deluge Team', 'manual')
]
# The name of an image file (relative to this directory) to place at the top of
diff --git a/gen_web_gettext.py b/gen_web_gettext.py
index a769ae3aa..fac509736 100755
--- a/gen_web_gettext.py
+++ b/gen_web_gettext.py
@@ -46,7 +46,10 @@ def check_missing_markup(js_dir):
# Create a list of the matching strings to search for with the except_chars appended to each one.
string_re = re.compile(
- '(' + ')|('.join(['%s[^' + except_chars + "].*'"] * len(attr_list)) % tuple(attr_list) + ')',
+ '('
+ + ')|('.join(['%s[^' + except_chars + "].*'"] * len(attr_list))
+ % tuple(attr_list)
+ + ')'
)
strings = {}
@@ -58,10 +61,16 @@ def check_missing_markup(js_dir):
for match in string_re.finditer(line):
for string in match.groups():
# Ignore string that contains only digits or specificied strings in skip.
- if not string or string.split('\'')[1].isdigit() or any(x in string for x in skip):
+ if (
+ not string
+ or string.split('\'')[1].isdigit()
+ or any(x in string for x in skip)
+ ):
continue
locations = strings.get(string, [])
- locations.append((os.path.join(root, filename), str(lineno + 1)))
+ locations.append(
+ (os.path.join(root, filename), str(lineno + 1))
+ )
strings[string] = locations
return strings
@@ -70,8 +79,9 @@ GETTEXT_TPL = (
'GetText={maps:{},'
'add:function(string,translation){this.maps[string]=translation},'
'get:function(string){if (this.maps[string]){string=this.maps[string]} return string}};'
- 'function _(string){return GetText.get(string)}')
-GETTEXT_SUBST_TPL = ("GetText.add('{key}','${{escape(_(\"{key}\"))}}')\n")
+ 'function _(string){return GetText.get(string)}'
+)
+GETTEXT_SUBST_TPL = "GetText.add('{key}','${{escape(_(\"{key}\"))}}')\n"
def create_gettext_js(js_dir):
@@ -94,7 +104,9 @@ def create_gettext_js(js_dir):
fp.write(GETTEXT_TPL)
for key in sorted(strings):
if DEBUG:
- fp.write('\n//: %s' % '//: '.join(['%s:%s\n' % x for x in strings[key]]))
+ fp.write(
+ '\n//: %s' % '//: '.join(['%s:%s\n' % x for x in strings[key]])
+ )
fp.write(GETTEXT_SUBST_TPL.format(key=key))
return gettext_file
diff --git a/generate_pot.py b/generate_pot.py
index 470b8f40c..257327af7 100755
--- a/generate_pot.py
+++ b/generate_pot.py
@@ -22,11 +22,7 @@ from gen_web_gettext import create_gettext_js
from version import get_version
# Paths to exclude
-EXCLUSIONS = [
- 'deluge/scripts',
- 'deluge/i18n',
- 'deluge/tests',
-]
+EXCLUSIONS = ['deluge/scripts', 'deluge/i18n', 'deluge/tests']
WEBUI_JS_DIR = 'deluge/ui/web/js/deluge-all'
WEBUI_RENDER_DIR = 'deluge/ui/web/render'
INFILES_LIST = 'infiles.list'
diff --git a/minify_web_js.py b/minify_web_js.py
index d9a1643a9..4d65c197b 100755
--- a/minify_web_js.py
+++ b/minify_web_js.py
@@ -35,13 +35,25 @@ def module_exists(module_name):
# Imports sorted by resulting file size.
if module_exists('closure'):
+
def minify_closure(file_in, file_out):
try:
- subprocess.check_call(['closure', '-W', 'QUIET',
- '--js', file_in, '--js_output_file', file_out])
+ subprocess.check_call(
+ [
+ 'closure',
+ '-W',
+ 'QUIET',
+ '--js',
+ file_in,
+ '--js_output_file',
+ file_out,
+ ]
+ )
return True
except subprocess.CalledProcessError:
return False
+
+
elif module_exists('slimit'):
from slimit import minify
else:
@@ -108,7 +120,10 @@ def minify_js_dir(source_dir):
if __name__ == '__main__':
if len(sys.argv) != 2:
- JS_SOURCE_DIRS = ['deluge/ui/web/js/deluge-all', 'deluge/ui/web/js/extjs/ext-extensions']
+ JS_SOURCE_DIRS = [
+ 'deluge/ui/web/js/deluge-all',
+ 'deluge/ui/web/js/extjs/ext-extensions',
+ ]
else:
JS_SOURCE_DIRS = [os.path.abspath(sys.argv[1])]
diff --git a/msgfmt.py b/msgfmt.py
index 201c09924..c0e093ab6 100755
--- a/msgfmt.py
+++ b/msgfmt.py
@@ -68,8 +68,14 @@ def generate():
for _id in keys:
# For each string, we need size and file offset when encoded. Each string is NUL
# terminated; the NUL does not count into the size.
- offsets.append((len(ids.encode('utf8')), len(_id.encode('utf8')),
- len(strs.encode('utf8')), len(MESSAGES[_id].encode('utf8'))))
+ offsets.append(
+ (
+ len(ids.encode('utf8')),
+ len(_id.encode('utf8')),
+ len(strs.encode('utf8')),
+ len(MESSAGES[_id].encode('utf8')),
+ )
+ )
ids += _id + '\x00'
strs += MESSAGES[_id] + '\x00'
@@ -87,13 +93,16 @@ def generate():
koffsets += [l1, o1 + keystart]
voffsets += [l2, o2 + valuestart]
offsets = koffsets + voffsets
- output = struct.pack('Iiiiiii',
- 0x950412de, # Magic
- 0, # Version
- len(keys), # # of entries
- 7 * 4, # start of key index
- 7 * 4 + len(keys) * 8, # start of value index
- 0, 0) # size and offset of hash table
+ output = struct.pack(
+ 'Iiiiiii',
+ 0x950412DE, # Magic
+ 0, # Version
+ len(keys), # # of entries
+ 7 * 4, # start of key index
+ 7 * 4 + len(keys) * 8, # start of value index
+ 0,
+ 0,
+ ) # size and offset of hash table
if sys.version_info.major == 2:
output += array.array(b'i', offsets).tostring()
else:
@@ -119,6 +128,7 @@ def make(filename, outfile):
try:
import io
+
with io.open(infile, encoding='utf8') as _file:
lines = _file.readlines()
except IOError as msg:
@@ -165,7 +175,7 @@ def make(filename, outfile):
if not line.startswith('[0]'):
msgstr += '\x00'
# Ignore the index - must come in sequence
- line = line[line.index(']') + 1:]
+ line = line[line.index(']') + 1 :]
# Skip empty lines
line = line.strip()
if not line:
@@ -198,8 +208,9 @@ def make(filename, outfile):
def main():
try:
- opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
- ['help', 'version', 'output-file='])
+ opts, args = getopt.getopt(
+ sys.argv[1:], 'hVo:', ['help', 'version', 'output-file=']
+ )
except getopt.error as msg:
usage(1, msg)
diff --git a/packaging/source/make_release.py b/packaging/source/make_release.py
index 62806f04e..542897ed0 100755
--- a/packaging/source/make_release.py
+++ b/packaging/source/make_release.py
@@ -31,7 +31,11 @@ version = check_output(['python', 'version.py']).strip()
# Create release archive
release_dir = 'dist/release-%s' % version
print('Creating release archive for ' + version)
-call('python setup.py --quiet egg_info --egg-base /tmp sdist --formats=tar --dist-dir=%s' % release_dir, shell=True)
+call(
+ 'python setup.py --quiet egg_info --egg-base /tmp sdist --formats=tar --dist-dir=%s'
+ % release_dir,
+ shell=True,
+)
# Compress release archive with xz
tar_path = os.path.join(release_dir, 'deluge-%s.tar' % version)
@@ -39,13 +43,18 @@ tarxz_path = tar_path + '.xz'
print('Compressing tar (%s) with xz' % tar_path)
if lzma:
with open(tar_path, 'rb') as tar_file, open(tarxz_path, 'wb') as xz_file:
- xz_file.write(lzma.compress(bytes(tar_file.read()), preset=9 | lzma.PRESET_EXTREME))
+ xz_file.write(
+ lzma.compress(bytes(tar_file.read()), preset=9 | lzma.PRESET_EXTREME)
+ )
else:
call(['xz', '-e9zkf', tar_path])
# Calculate shasum and add to sha256sums.txt
with open(tarxz_path, 'rb') as _file:
- sha256sum = '%s %s' % (sha256(_file.read()).hexdigest(), os.path.basename(tarxz_path))
+ sha256sum = '%s %s' % (
+ sha256(_file.read()).hexdigest(),
+ os.path.basename(tarxz_path),
+ )
with open(os.path.join(release_dir, 'sha256sums.txt'), 'w') as _file:
_file.write(sha256sum + '\n')
diff --git a/packaging/win32/deluge-bbfreeze.py b/packaging/win32/deluge-bbfreeze.py
index 54aefb49f..400bf640f 100644
--- a/packaging/win32/deluge-bbfreeze.py
+++ b/packaging/win32/deluge-bbfreeze.py
@@ -27,10 +27,21 @@ import deluge.common
class VersionInfo(object):
- def __init__(self, version, internalname=None, originalfilename=None,
- comments=None, company=None, description=None,
- _copyright=None, trademarks=None, product=None, dll=False,
- debug=False, verbose=True):
+ def __init__(
+ self,
+ version,
+ internalname=None,
+ originalfilename=None,
+ comments=None,
+ company=None,
+ description=None,
+ _copyright=None,
+ trademarks=None,
+ product=None,
+ dll=False,
+ debug=False,
+ verbose=True,
+ ):
parts = version.split('.')
while len(parts) < 4:
parts.append('0')
@@ -71,8 +82,19 @@ if not DEBUG:
sys.stdout = open(os.devnull, 'w')
# Include python modules not picked up automatically by bbfreeze.
-includes = ('libtorrent', 'cairo', 'pangocairo', 'atk', 'pango', 'twisted.internet.utils',
- 'gio', 'gzip', 'email.mime.multipart', 'email.mime.text', '_cffi_backend')
+includes = (
+ 'libtorrent',
+ 'cairo',
+ 'pangocairo',
+ 'atk',
+ 'pango',
+ 'twisted.internet.utils',
+ 'gio',
+ 'gzip',
+ 'email.mime.multipart',
+ 'email.mime.text',
+ '_cffi_backend',
+)
excludes = ('numpy', 'OpenGL', 'psyco', 'win32ui', 'unittest')
@@ -86,11 +108,17 @@ bbfreeze.recipes.recipe_gtk_and_friends = recipe_gtk_override
# Workaround for "ImportError: The 'packaging' package is required" with setuptools > 18.8.
# (https://github.com/pypa/setuptools/issues/517)
-bbfreeze.recipes.recipe_pkg_resources = bbfreeze.recipes.include_whole_package('pkg_resources')
+bbfreeze.recipes.recipe_pkg_resources = bbfreeze.recipes.include_whole_package(
+ 'pkg_resources'
+)
fzr = bbfreeze.Freezer(build_dir, includes=includes, excludes=excludes)
fzr.include_py = False
-fzr.setIcon(os.path.join(os.path.dirname(deluge.common.__file__), 'ui', 'data', 'pixmaps', 'deluge.ico'))
+fzr.setIcon(
+ os.path.join(
+ os.path.dirname(deluge.common.__file__), 'ui', 'data', 'pixmaps', 'deluge.ico'
+ )
+)
# TODO: Can/should we grab the script list from setup.py entry_points somehow.
@@ -125,10 +153,22 @@ for script in script_list:
os.remove(script)
# Exclude files which are already included in GTK or Windows. Also exclude unneeded pygame dlls.
-excludeDlls = ('MSIMG32.dll', 'MSVCR90.dll', 'MSVCP90.dll', 'MSVCR120.dll',
- 'POWRPROF.dll', 'DNSAPI.dll', 'USP10.dll', 'MPR.dll',
- 'jpeg.dll', 'libfreetype-6.dll', 'libpng12-0.dll', 'libtiff.dll',
- 'SDL_image.dll', 'SDL_ttf.dll')
+excludeDlls = (
+ 'MSIMG32.dll',
+ 'MSVCR90.dll',
+ 'MSVCP90.dll',
+ 'MSVCR120.dll',
+ 'POWRPROF.dll',
+ 'DNSAPI.dll',
+ 'USP10.dll',
+ 'MPR.dll',
+ 'jpeg.dll',
+ 'libfreetype-6.dll',
+ 'libpng12-0.dll',
+ 'libtiff.dll',
+ 'SDL_image.dll',
+ 'SDL_ttf.dll',
+)
for exclude_dll in excludeDlls:
try:
os.remove(os.path.join(build_dir, exclude_dll))
@@ -146,13 +186,16 @@ locale_include_list = ['gtk20.mo', 'locale.alias']
def ignored_files(adir, ignore_filenames):
return [
- ignore_file for ignore_file in ignore_filenames
- if not os.path.isdir(os.path.join(adir, ignore_file)) and
- ignore_file not in locale_include_list
+ ignore_file
+ for ignore_file in ignore_filenames
+ if not os.path.isdir(os.path.join(adir, ignore_file))
+ and ignore_file not in locale_include_list
]
-shutil.copytree(gtk_locale, os.path.join(build_dir, 'share/locale'), ignore=ignored_files)
+shutil.copytree(
+ gtk_locale, os.path.join(build_dir, 'share/locale'), ignore=ignored_files
+)
# Copy gtk theme files.
theme_include_list = [
@@ -180,11 +223,13 @@ for script in script_list:
script_exe = os.path.splitext(os.path.basename(script))[0] + '.exe'
# Don't add to dev build versions.
if not re.search('[a-zA-Z_-]', build_version):
- versionInfo = VersionInfo(build_version,
- description='Deluge Bittorrent Client',
- company='Deluge Team',
- product='Deluge',
- _copyright='Deluge Team')
+ versionInfo = VersionInfo(
+ build_version,
+ description='Deluge Bittorrent Client',
+ company='Deluge Team',
+ product='Deluge',
+ _copyright='Deluge Team',
+ )
stamp(os.path.join(build_dir, script_exe), versionInfo)
# Copy version info to file for nsis script.
@@ -196,7 +241,7 @@ filedir_list = []
for root, dirnames, filenames in os.walk(build_dir):
dirnames.sort()
filenames.sort()
- filedir_list.append((root[len(build_dir):], filenames))
+ filedir_list.append((root[len(build_dir) :], filenames))
with open('install_files.nsh', 'w') as f:
f.write('; Files to install\n')
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..8962ece64
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,8 @@
+[build-system]
+requires = [
+ "setuptools",
+ "wheel",
+]
+
+[tool.black]
+skip-string-normalization = true
diff --git a/setup.cfg b/setup.cfg
index 9fee85746..8d62dd2a6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -25,5 +25,26 @@ known_third_party =
pygtk, gtk, gobject, gtk.gdk, pango, cairo, pangocairo
known_first_party = msgfmt, deluge
order_by_type = true
-line_length = 120
not_skip = __init__.py
+# Black compatible settings
+multi_line_output=3
+include_trailing_comma=True
+force_grid_wrap=0
+line_length=88
+use_parentheses=True
+
+[flake8]
+max-line-length = 120
+builtins = _,_n,__request__
+exclude = .git,.tox,dist,build
+ignore =
+# A003 Class attribute is a python builtin.
+ A003,
+# C813, C815, C816: PY3 missing trailing commas.
+ C813,C815,C816,
+# W503 line break before binary operator.
+ W503,
+ E203
+
+[pycodestyle]
+max-line-length = 88
diff --git a/setup.py b/setup.py
index 43710f09f..941f890bc 100755
--- a/setup.py
+++ b/setup.py
@@ -30,6 +30,7 @@ from version import get_version
try:
from sphinx.setup_command import BuildDoc
except ImportError:
+
class BuildDoc(object):
pass
@@ -54,7 +55,6 @@ _version = get_version(prefix='deluge-', suffix='.dev0')
class PyTest(_test):
-
def initialize_options(self):
_test.initialize_options(self)
self.pytest_args = []
@@ -66,6 +66,7 @@ class PyTest(_test):
def run_tests(self):
import pytest
+
errcode = pytest.main(self.test_args)
sys.exit(errcode)
@@ -116,6 +117,7 @@ class BuildWebUI(cmd.Command):
try:
from minify_web_js import minify_js_dir
+
import_error = ''
except ImportError as err:
import_error = err
@@ -127,7 +129,11 @@ class BuildWebUI(cmd.Command):
except NameError:
js_file = source_dir + '.js'
if os.path.isfile(js_file):
- print('Unable to minify but found existing minified: {}'.format(js_file))
+ print(
+ 'Unable to minify but found existing minified: {}'.format(
+ js_file
+ )
+ )
else:
# Unable to minify and no existing minified file found so exiting.
print('Import error: %s' % import_error)
@@ -202,15 +208,19 @@ class BuildTranslations(cmd.Command):
intltool_merge_opts += ' --desktop-style'
print('Creating file: %s' % data_file)
- os.system('C_ALL=C ' + '%s ' * 5 % (
- intltool_merge, intltool_merge_opts, po_dir, in_file, data_file))
+ os.system(
+ 'C_ALL=C '
+ + '%s '
+ * 5
+ % (intltool_merge, intltool_merge_opts, po_dir, in_file, data_file)
+ )
print('Compiling po files from %s...' % po_dir)
for path, names, filenames in os.walk(po_dir):
for f in filenames:
upto_date = False
if f.endswith('.po'):
- lang = f[:len(f) - 3]
+ lang = f[: len(f) - 3]
src = os.path.join(path, f)
dest_path = os.path.join(basedir, lang, 'LC_MESSAGES')
dest = os.path.join(dest_path, 'deluge.mo')
@@ -237,7 +247,9 @@ class BuildTranslations(cmd.Command):
class CleanTranslations(cmd.Command):
description = 'Cleans translations files.'
- user_options = [('all', 'a', 'Remove all build output, not just temporary by-products')]
+ user_options = [
+ ('all', 'a', 'Remove all build output, not just temporary by-products')
+ ]
boolean_options = ['all']
def initialize_options(self):
@@ -276,17 +288,32 @@ class BuildPlugins(cmd.Command):
for path in glob.glob(plugin_path):
if os.path.exists(os.path.join(path, 'setup.py')):
if self.develop and self.install_dir:
- os.system('cd ' + path + '&& ' + sys.executable +
- ' setup.py develop --install-dir=%s' % self.install_dir)
+ os.system(
+ 'cd '
+ + path
+ + '&& '
+ + sys.executable
+ + ' setup.py develop --install-dir=%s' % self.install_dir
+ )
elif self.develop:
- os.system('cd ' + path + '&& ' + sys.executable + ' setup.py develop')
+ os.system(
+ 'cd ' + path + '&& ' + sys.executable + ' setup.py develop'
+ )
else:
- os.system('cd ' + path + '&& ' + sys.executable + ' setup.py bdist_egg -d ..')
+ os.system(
+ 'cd '
+ + path
+ + '&& '
+ + sys.executable
+ + ' setup.py bdist_egg -d ..'
+ )
class CleanPlugins(cmd.Command):
description = 'Cleans the plugin folders'
- user_options = [('all', 'a', 'Remove all build output, not just temporary by-products')]
+ user_options = [
+ ('all', 'a', 'Remove all build output, not just temporary by-products')
+ ]
boolean_options = ['all']
def initialize_options(self):
@@ -361,6 +388,7 @@ class Build(_build):
_build.run(self)
try:
from deluge._libtorrent import LT_VERSION
+
print('Info: Found libtorrent ({}) installed.'.format(LT_VERSION))
except ImportError as ex:
print('Warning: libtorrent (libtorrent-rasterbar) not found: %s' % ex)
@@ -371,8 +399,12 @@ class InstallData(_install_data):
def finalize_options(self):
self.install_dir = None
- self.set_undefined_options('install', ('install_data', 'install_dir'),
- ('root', 'root'), ('force', 'force'))
+ self.set_undefined_options(
+ 'install',
+ ('install_data', 'install_dir'),
+ ('root', 'root'),
+ ('force', 'force'),
+ )
def run(self):
_install_data.run(self)
@@ -382,7 +414,8 @@ class Clean(_clean):
sub_commands = _clean.sub_commands + [
('clean_plugins', None),
('clean_trans', None),
- ('clean_webui', None)]
+ ('clean_webui', None),
+ ]
def run(self):
# Remove deluge egg-info.
@@ -420,16 +453,30 @@ if not windows_check() and not osx_check():
for icon_path in glob.glob('deluge/ui/data/icons/hicolor/*x*'):
size = os.path.basename(icon_path)
_data_files.append(
- ('share/icons/hicolor/{}/apps'.format(size), ['{}/apps/deluge.png'.format(icon_path)]))
- _data_files.extend([
- ('share/icons/hicolor/scalable/apps', ['deluge/ui/data/icons/hicolor/scalable/apps/deluge.svg']),
- ('share/pixmaps', ['deluge/ui/data/pixmaps/deluge.png']),
- ('share/man/man1', [
- 'docs/man/deluge.1',
- 'docs/man/deluged.1',
- 'docs/man/deluge-gtk.1',
- 'docs/man/deluge-web.1',
- 'docs/man/deluge-console.1'])])
+ (
+ 'share/icons/hicolor/{}/apps'.format(size),
+ ['{}/apps/deluge.png'.format(icon_path)],
+ )
+ )
+ _data_files.extend(
+ [
+ (
+ 'share/icons/hicolor/scalable/apps',
+ ['deluge/ui/data/icons/hicolor/scalable/apps/deluge.svg'],
+ ),
+ ('share/pixmaps', ['deluge/ui/data/pixmaps/deluge.png']),
+ (
+ 'share/man/man1',
+ [
+ 'docs/man/deluge.1',
+ 'docs/man/deluged.1',
+ 'docs/man/deluge-gtk.1',
+ 'docs/man/deluge-web.1',
+ 'docs/man/deluge-console.1',
+ ],
+ ),
+ ]
+ )
if os.path.isfile(desktop_data):
_data_files.append(('share/applications', [desktop_data]))
if os.path.isfile(appdata_data):
@@ -438,19 +485,25 @@ if not windows_check() and not osx_check():
_entry_points['console_scripts'] = [
'deluge-console = deluge.ui.console:start',
'deluge-web = deluge.ui.web:start',
- 'deluged = deluge.core.daemon_entry:start_daemon']
+ 'deluged = deluge.core.daemon_entry:start_daemon',
+]
if windows_check():
- _entry_points['console_scripts'].extend([
- 'deluge-debug = deluge.ui.ui_entry:start_ui',
- 'deluge-web-debug = deluge.ui.web:start',
- 'deluged-debug = deluge.core.daemon_entry:start_daemon'])
+ _entry_points['console_scripts'].extend(
+ [
+ 'deluge-debug = deluge.ui.ui_entry:start_ui',
+ 'deluge-web-debug = deluge.ui.web:start',
+ 'deluged-debug = deluge.core.daemon_entry:start_daemon',
+ ]
+ )
_entry_points['gui_scripts'] = [
'deluge = deluge.ui.ui_entry:start_ui',
- 'deluge-gtk = deluge.ui.gtkui:start']
+ 'deluge-gtk = deluge.ui.gtkui:start',
+]
_entry_points['deluge.ui'] = [
'console = deluge.ui.console:Console',
'web = deluge.ui.web:Web',
- 'gtk = deluge.ui.gtkui:Gtk']
+ 'gtk = deluge.ui.gtkui:Gtk',
+]
_package_data['deluge'] = [
@@ -460,7 +513,8 @@ _package_data['deluge'] = [
'ui/data/pixmaps/*.gif',
'ui/data/pixmaps/flags/*.png',
'plugins/*.egg',
- 'i18n/*/LC_MESSAGES/*.mo']
+ 'i18n/*/LC_MESSAGES/*.mo',
+]
_package_data['deluge.ui.web'] = [
'index.html',
'css/*.css',
@@ -474,18 +528,14 @@ _package_data['deluge.ui.web'] = [
'themes/images/*/*.gif',
'themes/images/*/*.png',
'themes/images/*/*/*.gif',
- 'themes/images/*/*/*.png']
+ 'themes/images/*/*/*.png',
+]
_package_data['deluge.ui.gtkui'] = ['glade/*.ui']
if 'dev' not in _version:
_exclude_package_data['deluge.ui.web'] = ['*-debug.js', '*-debug.css']
-docs_require = [
- 'Sphinx',
- 'recommonmark',
- 'sphinx-rtd-theme',
- 'sphinxcontrib-spelling',
-]
+docs_require = ['Sphinx', 'recommonmark', 'sphinx-rtd-theme', 'sphinxcontrib-spelling']
tests_require = [
'coverage',
'flake8',
@@ -527,13 +577,16 @@ setup(
'Environment :: X11 Applications :: GTK',
'Framework :: Twisted',
'Intended Audience :: End Users/Desktop',
- ('License :: OSI Approved :: '
- 'GNU General Public License v3 or later (GPLv3+)'),
+ (
+ 'License :: OSI Approved :: '
+ 'GNU General Public License v3 or later (GPLv3+)'
+ ),
'Programming Language :: Python',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
- 'Topic :: Internet'],
+ 'Topic :: Internet',
+ ],
license='GPLv3',
cmdclass=cmdclass,
extras_require={
diff --git a/tox.ini b/tox.ini
index 52626d3e2..3e4b05a7e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,21 +3,6 @@
#
# Usage: `pip install tox` and then run `tox` from this directory.
-[flake8]
-max-line-length = 120
-builtins = _,_n,__request__
-exclude = .git,.tox,dist,build
-ignore =
-# A003 Class attribute is a python builtin.
- A003,
-# C813, C815, C816: PY3 missing trailing commas.
- C813,C815,C816,
-# W503 line break before binary operator.
- W503,
-
-[pycodestyle]
-max-line-length = 120
-
[tox]
envlist = py27, flake8, docs
minversion=2.0
diff --git a/version.py b/version.py
index 3d9a550b4..2f2fc81ff 100755
--- a/version.py
+++ b/version.py
@@ -36,7 +36,7 @@ from __future__ import print_function, unicode_literals
import os
from subprocess import PIPE, Popen
-__all__ = ('get_version')
+__all__ = ('get_version',)
VERSION_FILE = os.path.join(os.path.dirname(__file__), 'RELEASE-VERSION')