diff options
Diffstat (limited to 'deluge/plugins/Stats')
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/__init__.py | 9 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/common.py | 3 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/core.py | 65 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/data/config.ui~ | 280 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/data/stats.js | 6 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/graph.py | 13 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/gtkui.py | 9 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/tests/test_stats.py | 60 | ||||
-rw-r--r-- | deluge/plugins/Stats/deluge_stats/webui.py | 3 | ||||
-rw-r--r-- | deluge/plugins/Stats/setup.py | 1 |
10 files changed, 74 insertions, 375 deletions
diff --git a/deluge/plugins/Stats/deluge_stats/__init__.py b/deluge/plugins/Stats/deluge_stats/__init__.py index a40379b..ca7b0bb 100644 --- a/deluge/plugins/Stats/deluge_stats/__init__.py +++ b/deluge/plugins/Stats/deluge_stats/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> # @@ -11,8 +10,6 @@ # See LICENSE for more details. # -from __future__ import unicode_literals - from deluge.plugins.init import PluginInitBase @@ -21,7 +18,7 @@ class CorePlugin(PluginInitBase): from .core import Core as _pluginCls self._plugin_cls = _pluginCls - super(CorePlugin, self).__init__(plugin_name) + super().__init__(plugin_name) class GtkUIPlugin(PluginInitBase): @@ -29,7 +26,7 @@ class GtkUIPlugin(PluginInitBase): from .gtkui import GtkUI as _pluginCls self._plugin_cls = _pluginCls - super(GtkUIPlugin, self).__init__(plugin_name) + super().__init__(plugin_name) class WebUIPlugin(PluginInitBase): @@ -37,4 +34,4 @@ class WebUIPlugin(PluginInitBase): from .webui import WebUI as _pluginCls self._plugin_cls = _pluginCls - super(WebUIPlugin, self).__init__(plugin_name) + super().__init__(plugin_name) diff --git a/deluge/plugins/Stats/deluge_stats/common.py b/deluge/plugins/Stats/deluge_stats/common.py index 4c9db09..eb47f13 100644 --- a/deluge/plugins/Stats/deluge_stats/common.py +++ b/deluge/plugins/Stats/deluge_stats/common.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Basic plugin template created by: # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> @@ -12,8 +11,6 @@ # See LICENSE for more details. # -from __future__ import unicode_literals - import os.path from pkg_resources import resource_filename diff --git a/deluge/plugins/Stats/deluge_stats/core.py b/deluge/plugins/Stats/deluge_stats/core.py index 635c54d..1be51e6 100644 --- a/deluge/plugins/Stats/deluge_stats/core.py +++ b/deluge/plugins/Stats/deluge_stats/core.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009 Ian Martin <ianmartin@cantab.net> # Copyright (C) 2008 Damien Churchill <damoxc@gmail.com> @@ -10,8 +9,6 @@ # See LICENSE for more details. # -from __future__ import division, unicode_literals - import logging import time @@ -77,16 +74,34 @@ class Core(CorePluginBase): self.length = self.config['length'] # self.stats = get_key(self.saved_stats, 'stats') or {} - self.stats_keys = ['peer.num_peers_half_open', 'dht.dht_node_cache'] - self.add_stats( + + # keys needed from core.get_session_status + self.stat_keys = [ 'upload_rate', 'download_rate', - 'dht_nodes', - 'dht_cache_nodes', - 'dht_torrents', - 'num_peers', - 'num_connections', - ) + 'dht.dht_nodes', + 'dht.dht_node_cache', + 'dht.dht_torrents', + 'peer.num_peers_connected', + 'peer.num_peers_half_open', + ] + # collected statistics and functions to get them + self.stat_getters = { + 'upload_rate': lambda s: s['upload_rate'], + 'download_rate': lambda s: s['download_rate'], + 'dht_nodes': lambda s: s['dht.dht_nodes'], + 'dht_cache_nodes': lambda s: s['dht.dht_node_cache'], + 'dht_torrents': lambda s: s['dht.dht_torrents'], + 'num_peers': lambda s: s['peer.num_peers_connected'], + 'num_connections': lambda s: s['peer.num_peers_connected'] + + s['peer.num_peers_half_open'], + } + + # initialize stats object + for key in self.stat_getters.keys(): + for i in self.intervals: + if key not in self.stats[i]: + self.stats[i][key] = [] self.update_stats() @@ -101,33 +116,13 @@ class Core(CorePluginBase): self.save_timer.stop() if self.save_timer.running else None self.save_stats() - def add_stats(self, *stats): - for stat in stats: - if stat not in self.stats_keys: - self.stats_keys.append(stat) - for i in self.intervals: - if stat not in self.stats[i]: - self.stats[i][stat] = [] - def update_stats(self): # Get all possible stats! stats = {} - for key in self.stats_keys: - # try all keys we have, very inefficient but saves having to - # work out where a key comes from... - try: - stats.update(self.core.get_session_status([key])) - except AttributeError: - pass - stats['num_connections'] = ( - stats['num_peers'] + stats['peer.num_peers_half_open'] - ) - stats['dht_cache_nodes'] = stats['dht.dht_node_cache'] - stats.update( - self.core.get_config_values( - ['max_download', 'max_upload', 'max_num_connections'] - ) - ) + raw_stats = self.core.get_session_status(self.stat_keys) + for name, fn in self.stat_getters.items(): + stats[name] = fn(raw_stats) + # status = self.core.session.status() # for stat in dir(status): # if not stat.startswith('_') and stat not in stats: diff --git a/deluge/plugins/Stats/deluge_stats/data/config.ui~ b/deluge/plugins/Stats/deluge_stats/data/config.ui~ deleted file mode 100644 index 25fc029..0000000 --- a/deluge/plugins/Stats/deluge_stats/data/config.ui~ +++ /dev/null @@ -1,280 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <requires lib="gtk+" version="3.0"/> - <!-- interface-naming-policy toplevel-contextual --> - <object class="GtkWindow" id="window1"> - <property name="can_focus">False</property> - <child> - <object class="GtkVBox" id="prefs_box"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkFrame" id="frame1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">15</property> - <child> - <object class="GtkTable" id="table2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="n_rows">10</property> - <property name="n_columns">2</property> - <property name="column_spacing">15</property> - <child> - <object class="GtkColorButton" id="bandwidth_graph_download_rate_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Download color:</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Upload color:</property> - </object> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="bandwidth_graph_upload_rate_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Connections Graph</b></property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Bandwidth Graph</b></property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="right_attach">2</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="connections_graph_dht_nodes_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label10"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">DHT nodes:</property> - </object> - <packing> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="connections_graph_dht_cache_nodes_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label11"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Cached DHT nodes:</property> - </object> - <packing> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label12"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">DHT torrents:</property> - </object> - <packing> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label13"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Connections:</property> - </object> - <packing> - <property name="top_attach">7</property> - <property name="bottom_attach">8</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="connections_graph_dht_torrents_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="connections_graph_num_connections_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">7</property> - <property name="bottom_attach">8</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label16"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Seeds / Peers</b></property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="right_attach">2</property> - <property name="top_attach">8</property> - <property name="bottom_attach">9</property> - </packing> - </child> - <child> - <object class="GtkColorButton" id="seeds_graph_num_peers_color"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="color">#000000000000</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">9</property> - <property name="bottom_attach">10</property> - <property name="x_options">GTK_EXPAND</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label17"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Peers:</property> - </object> - <packing> - <property name="top_attach">9</property> - <property name="bottom_attach">10</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes"><b>Graph Colors</b></property> - <property name="use_markup">True</property> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - </child> - </object> -</interface> diff --git a/deluge/plugins/Stats/deluge_stats/data/stats.js b/deluge/plugins/Stats/deluge_stats/data/stats.js index 8f9e3f8..7ba3d27 100644 --- a/deluge/plugins/Stats/deluge_stats/data/stats.js +++ b/deluge/plugins/Stats/deluge_stats/data/stats.js @@ -10,7 +10,7 @@ */ StatsPlugin = Ext.extend(Deluge.Plugin, { - constructor: function(config) { + constructor: function (config) { config = Ext.apply( { name: 'Stats', @@ -20,8 +20,8 @@ StatsPlugin = Ext.extend(Deluge.Plugin, { StatsPlugin.superclass.constructor.call(this, config); }, - onDisable: function() {}, + onDisable: function () {}, - onEnable: function() {}, + onEnable: function () {}, }); new StatsPlugin(); diff --git a/deluge/plugins/Stats/deluge_stats/graph.py b/deluge/plugins/Stats/deluge_stats/graph.py index 847c253..0d3220f 100644 --- a/deluge/plugins/Stats/deluge_stats/graph.py +++ b/deluge/plugins/Stats/deluge_stats/graph.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009 Ian Martin <ianmartin@cantab.net> # Copyright (C) 2008 Damien Churchill <damoxc@gmail.com> @@ -14,13 +13,15 @@ port of old plugin by markybob. """ -from __future__ import division, unicode_literals - import logging import math import time -from gi.repository import cairo +import gi + +gi.require_foreign('cairo') + +import cairo # isort:skip (gi checks required before import). log = logging.getLogger(__name__) @@ -58,7 +59,7 @@ def change_opacity(color, opactiy): return tuple(color) -class Graph(object): +class Graph: def __init__(self): self.width = 100 self.height = 100 @@ -174,7 +175,7 @@ class Graph(object): 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)) + y_tick_width = max(space_required(text) for text in y_tick_text) top = font_extents[2] / 2 # bounds(left, top, right, bottom) diff --git a/deluge/plugins/Stats/deluge_stats/gtkui.py b/deluge/plugins/Stats/deluge_stats/gtkui.py index 75e3015..c088060 100644 --- a/deluge/plugins/Stats/deluge_stats/gtkui.py +++ b/deluge/plugins/Stats/deluge_stats/gtkui.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009 Ian Martin <ianmartin@cantab.net> # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> @@ -12,8 +11,6 @@ # See LICENSE for more details. # -from __future__ import division, unicode_literals - import logging from gi.repository import Gtk @@ -85,7 +82,7 @@ def text_to_rgba(color): class GraphsTab(Tab): def __init__(self, colors): - super(GraphsTab, self).__init__() + super().__init__() builder = Gtk.Builder() builder.add_from_file(get_resource('tabs.ui')) @@ -270,7 +267,7 @@ class GtkUI(Gtk3PluginBase): for graph, colors in self.config['colors'].items(): gtkconf[graph] = {} for value, color in colors.items(): - color_btn = self.builder.get_object('%s_%s_color' % (graph, value)) + color_btn = self.builder.get_object(f'{graph}_{value}_color') try: gtkconf[graph][value] = color_btn.get_color().to_string() except Exception: @@ -285,7 +282,7 @@ class GtkUI(Gtk3PluginBase): for graph, colors in self.config['colors'].items(): for value, color in colors.items(): try: - color_btn = self.builder.get_object('%s_%s_color' % (graph, value)) + color_btn = self.builder.get_object(f'{graph}_{value}_color') color_btn.set_rgba(text_to_rgba(color)) except Exception as ex: log.debug('Unable to set %s %s %s: %s', graph, value, color, ex) diff --git a/deluge/plugins/Stats/deluge_stats/tests/test_stats.py b/deluge/plugins/Stats/deluge_stats/tests/test_stats.py index 3b581be..9c66ee1 100644 --- a/deluge/plugins/Stats/deluge_stats/tests/test_stats.py +++ b/deluge/plugins/Stats/deluge_stats/tests/test_stats.py @@ -1,19 +1,14 @@ -# -*- coding: utf-8 -*- # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. # -from __future__ import print_function, unicode_literals - import pytest +import pytest_twisted from twisted.internet import defer -from twisted.trial import unittest import deluge.component as component from deluge.common import fsize, fspeed -from deluge.tests import common as tests_common -from deluge.tests.basetest import BaseTestCase from deluge.ui.client import client @@ -26,42 +21,42 @@ def print_totals(totals): print('down:', fsize(totals['total_download'] - totals['total_payload_download'])) -class StatsTestCase(BaseTestCase): - def set_up(self): +@pytest.mark.usefixtures('component') +class TestStatsPlugin: + @pytest_twisted.async_yield_fixture(autouse=True) + async def set_up(self): defer.setDebugging(True) - tests_common.set_tmp_config_dir() client.start_standalone() client.core.enable_plugin('Stats') - return component.start() - - def tear_down(self): + await component.start() + yield client.stop_standalone() - return component.shutdown() + await component.shutdown() @defer.inlineCallbacks def test_client_totals(self): plugins = yield client.core.get_available_plugins() if 'Stats' not in plugins: - raise unittest.SkipTest('WebUi plugin not available for testing') + pytest.skip('Stats plugin not available for testing') totals = yield client.stats.get_totals() - self.assertEqual(totals['total_upload'], 0) - self.assertEqual(totals['total_payload_upload'], 0) - self.assertEqual(totals['total_payload_download'], 0) - self.assertEqual(totals['total_download'], 0) + assert totals['total_upload'] == 0 + assert totals['total_payload_upload'] == 0 + assert totals['total_payload_download'] == 0 + assert totals['total_download'] == 0 # print_totals(totals) @defer.inlineCallbacks def test_session_totals(self): plugins = yield client.core.get_available_plugins() if 'Stats' not in plugins: - raise unittest.SkipTest('WebUi plugin not available for testing') + pytest.skip('Stats plugin not available for testing') totals = yield client.stats.get_session_totals() - self.assertEqual(totals['total_upload'], 0) - self.assertEqual(totals['total_payload_upload'], 0) - self.assertEqual(totals['total_payload_download'], 0) - self.assertEqual(totals['total_download'], 0) + assert totals['total_upload'] == 0 + assert totals['total_payload_upload'] == 0 + assert totals['total_payload_download'] == 0 + assert totals['total_download'] == 0 # print_totals(totals) @pytest.mark.gtkui @@ -72,16 +67,17 @@ class StatsTestCase(BaseTestCase): Not strictly a unit test, but tests if calls do not fail... """ - from deluge.ui.gtkui.gtkui import DEFAULT_PREFS - from deluge.ui.gtkui.preferences import Preferences - from deluge.ui.gtkui.mainwindow import MainWindow - from deluge.configmanager import ConfigManager - from deluge.ui.gtkui.pluginmanager import PluginManager - from deluge.ui.gtkui.torrentdetails import TorrentDetails - from deluge.ui.gtkui.torrentview import TorrentView from deluge_stats import graph, gtkui - ConfigManager('gtkui.conf', defaults=DEFAULT_PREFS) + from deluge.configmanager import ConfigManager + from deluge.ui.gtk3.gtkui import DEFAULT_PREFS + from deluge.ui.gtk3.mainwindow import MainWindow + from deluge.ui.gtk3.pluginmanager import PluginManager + from deluge.ui.gtk3.preferences import Preferences + from deluge.ui.gtk3.torrentdetails import TorrentDetails + from deluge.ui.gtk3.torrentview import TorrentView + + ConfigManager('gtk3ui.conf', defaults=DEFAULT_PREFS) self.plugins = PluginManager() MainWindow() @@ -89,7 +85,7 @@ class StatsTestCase(BaseTestCase): TorrentDetails() Preferences() - class FakeFile(object): + class FakeFile: def __init__(self): self.data = [] diff --git a/deluge/plugins/Stats/deluge_stats/webui.py b/deluge/plugins/Stats/deluge_stats/webui.py index 4c11260..f38daeb 100644 --- a/deluge/plugins/Stats/deluge_stats/webui.py +++ b/deluge/plugins/Stats/deluge_stats/webui.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> # @@ -11,8 +10,6 @@ # See LICENSE for more details. # -from __future__ import unicode_literals - import logging from deluge.plugins.pluginbase import WebPluginBase diff --git a/deluge/plugins/Stats/setup.py b/deluge/plugins/Stats/setup.py index 174c652..0f3e069 100644 --- a/deluge/plugins/Stats/setup.py +++ b/deluge/plugins/Stats/setup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009 Ian Martin <ianmartin@cantab.net> # Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> |