summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalum Lind <calumlind@gmail.com>2018-10-02 15:39:51 +0100
committerCalum Lind <calumlind@gmail.com>2018-10-03 15:21:53 +0100
commitb1cdc32f7357e9777eb6cc2d90094c7d122af2eb (patch)
tree9106ac399a7df178c8dbed6fe58009d36b18159a
parentbcca07443ccad7f130444baaac52b7b49478905e (diff)
downloaddeluge-b1cdc32f7357e9777eb6cc2d90094c7d122af2eb.tar.gz
deluge-b1cdc32f7357e9777eb6cc2d90094c7d122af2eb.tar.bz2
deluge-b1cdc32f7357e9777eb6cc2d90094c7d122af2eb.zip
[Lint] Use Black to auto-format code
The move to using auto-formatter makes it easier to read, submit and speeds up development time. https://github.com/ambv/black/ Although I would prefer 79 chars, the default line length of 88 chars used by black suffices. The flake8 line length remains at 120 chars since black does not touch comments or docstrings and this will require another round of fixes. The only black setting that is not standard is the use of double-quotes for strings so disabled any formatting of these. Note however that flake8 will still flag usage of double-quotes. I may change my mind on double vs single quotes but for now leave them. A new pyproject.toml file has been created for black configuration.
-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')