Test Failed
Push — develop ( fdd819...a14634 )
by Nicolas
02:40 queued 17s
created

PluginModel.generate_view_data()   D

Complexity

Conditions 10

Size

Total Lines 97
Code Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 81
nop 1
dl 0
loc 97
rs 4.8218
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like glances.plugins.help.PluginModel.generate_view_data() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
10
"""
11
Help plugin.
12
13
Just a stupid plugin to display the help screen.
14
"""
15
import sys
16
from glances.globals import iteritems
17
from glances import __version__, psutil_version
18
from glances.plugins.plugin.model import GlancesPluginModel
19
from itertools import chain
20
21
22
class PluginModel(GlancesPluginModel):
23
    """Glances help plugin."""
24
25
    def __init__(self, args=None, config=None):
26
        """Init the plugin."""
27
        super(PluginModel, self).__init__(args=args, config=config)
28
29
        # Set the config instance
30
        self.config = config
31
        self.args = args
32
33
        # We want to display the stat in the curse interface
34
        self.display_curse = True
35
36
        # init data dictionary, to preserve insertion order
37
        if sys.version_info < (3, 6):
38
            from collections import OrderedDict
39
40
            self.view_data = OrderedDict()
41
        else:
42
            self.view_data = {}
43
        self.generate_view_data()
44
45
    def reset(self):
46
        """No stats. It is just a plugin to display the help."""
47
48
    def update(self):
49
        """No stats. It is just a plugin to display the help."""
50
51
    def generate_view_data(self):
52
        """Generate the views."""
53
        self.view_data['version'] = '{} {}'.format('Glances', __version__)
54
        self.view_data['psutil_version'] = ' with psutil {}'.format(psutil_version)
55
56
        try:
57
            self.view_data['configuration_file'] = 'Configuration file: {}'.format(self.config.loaded_config_file)
58
        except AttributeError:
59
            pass
60
61
        msg_col = '  {0:1}  {1:34}'
62
        msg_header = '{0:39}'
63
64
        self.view_data.update(
65
            [
66
                # First column
67
                #
68
                ('header_sort', msg_header.format('SORT PROCESSES:')),
69
                ('sort_auto', msg_col.format('a', 'Automatically')),
70
                ('sort_cpu', msg_col.format('c', 'CPU%')),
71
                ('sort_io_rate', msg_col.format('i', 'I/O rate')),
72
                ('sort_mem', msg_col.format('m', 'MEM%')),
73
                ('sort_process_name', msg_col.format('p', 'Process name')),
74
                ('sort_cpu_times', msg_col.format('t', 'TIME')),
75
                ('sort_user', msg_col.format('u', 'USER')),
76
                ('header_show_hide', msg_header.format('SHOW/HIDE SECTION:')),
77
                ('show_hide_application_monitoring', msg_col.format('A', 'Application monitoring')),
78
                ('show_hide_diskio', msg_col.format('d', 'Disk I/O')),
79
                ('show_hide_docker', msg_col.format('D', 'Docker')),
80
                ('show_hide_top_extended_stats', msg_col.format('e', 'Top extended stats')),
81
                ('show_hide_filesystem', msg_col.format('f', 'Filesystem')),
82
                ('show_hide_gpu', msg_col.format('G', 'GPU')),
83
                ('show_hide_ip', msg_col.format('I', 'IP')),
84
                ('show_hide_tcp_connection', msg_col.format('K', 'TCP')),
85
                ('show_hide_alert', msg_col.format('l', 'Alert logs')),
86
                ('show_hide_network', msg_col.format('n', 'Network')),
87
                ('show_hide_current_time', msg_col.format('N', 'Time')),
88
                ('show_hide_irq', msg_col.format('Q', 'IRQ')),
89
                ('show_hide_raid_plugin', msg_col.format('R', 'RAID')),
90
                ('show_hide_sensors', msg_col.format('s', 'Sensors')),
91
                ('show_hide_wifi_module', msg_col.format('W', 'Wifi')),
92
                ('show_hide_processes', msg_col.format('z', 'Processes')),
93
                ('show_hide_left_sidebar', msg_col.format('2', 'Left sidebar')),
94
                # Second column
95
                #
96
                ('show_hide_quick_look', msg_col.format('3', 'Quick Look')),
97
                ('show_hide_cpu_mem_swap', msg_col.format('4', 'CPU, MEM, and SWAP')),
98
                ('show_hide_all', msg_col.format('5', 'ALL')),
99
                ('header_toggle', msg_header.format('TOGGLE DATA TYPE:')),
100
                ('toggle_bits_bytes', msg_col.format('b', 'Network I/O, bits/bytes')),
101
                ('toggle_count_rate', msg_col.format('B', 'Disk I/O, count/rate')),
102
                ('toggle_used_free', msg_col.format('F', 'Filesystem space, used/free')),
103
                ('toggle_bar_sparkline', msg_col.format('S', 'Quick Look, bar/sparkline')),
104
                ('toggle_separate_combined', msg_col.format('T', 'Network I/O, separate/combined')),
105
                ('toggle_live_cumulative', msg_col.format('U', 'Network I/O, live/cumulative')),
106
                ('toggle_linux_percentage', msg_col.format('0', 'Load, Linux/percentage')),
107
                ('toggle_cpu_individual_combined', msg_col.format('1', 'CPU, individual/combined')),
108
                ('toggle_gpu_individual_combined', msg_col.format('6', 'GPU, individual/combined')),
109
                (
110
                    'toggle_short_full',
111
                    (
112
                        msg_col.format('S', 'Process names, short/full')
113
                        if self.args and self.args.webserver
114
                        else msg_col.format('/', 'Process names, short/full')
115
                    ),
116
                ),
117
                ('header_miscellaneous', msg_header.format('MISCELLANEOUS:')),
118
                (
119
                    'misc_erase_process_filter',
120
                    '' if self.args and self.args.webserver else msg_col.format('E', 'Erase process filter'),
121
                ),
122
                (
123
                    'misc_generate_history_graphs',
124
                    '' if self.args and self.args.webserver else msg_col.format('g', 'Generate history graphs'),
125
                ),
126
                ('misc_help', msg_col.format('h', 'HELP')),
127
                (
128
                    'misc_accumulate_processes_by_program',
129
                    '' if self.args and self.args.webserver else msg_col.format('j', 'Display threads or programs'),
130
                ),
131
                ('misc_increase_nice_process', msg_col.format('+', 'Increase nice process')),
132
                ('misc_decrease_nice_process', msg_col.format('-', 'Decrease nice process (need admin rights)')),
133
                ('misc_kill_process', '' if self.args and self.args.webserver else msg_col.format('k', 'Kill process')),
134
                (
135
                    'misc_reset_processes_summary_min_max',
136
                    '' if self.args and self.args.webserver else msg_col.format('M', 'Reset processes summary min/max'),
137
                ),
138
                (
139
                    'misc_quit',
140
                    '' if self.args and self.args.webserver else msg_col.format('q', 'QUIT (or Esc or Ctrl-C)'),
141
                ),
142
                ('misc_reset_history', msg_col.format('r', 'Reset history')),
143
                ('misc_delete_warning_alerts', msg_col.format('w', 'Delete warning alerts')),
144
                ('misc_delete_warning_and_critical_alerts', msg_col.format('x', 'Delete warning & critical alerts')),
145
                (
146
                    'misc_edit_process_filter_pattern',
147
                    '' if self.args and self.args.webserver else '  ENTER: Edit process filter pattern',
148
                ),
149
            ]
150
        )
151
152
    def get_view_data(self, args=None):
153
        """Return the view."""
154
        return self.view_data
155
156
    def msg_curse(self, args=None, max_width=None):
157
        """Return the list to display in the curse interface."""
158
        # Init the return message
159
        ret = []
160
161
        # Build the header message
162
        ret.append(self.curse_add_line(self.view_data['version'], 'TITLE'))
163
        ret.append(self.curse_add_line(self.view_data['psutil_version']))
164
        ret.append(self.curse_new_line())
165
166
        # Build the configuration file path
167
        if 'configuration_file' in self.view_data:
168
            ret.append(self.curse_add_line(self.view_data['configuration_file']))
169
            ret.append(self.curse_new_line())
170
171
        ret.append(self.curse_new_line())
172
173
        # key-shortcuts
174
        #
175
        # Collect all values after the 1st key-msg
176
        # in a list of curse-lines.
177
        #
178
        shortcuts = []
179
        collecting = False
180
        for k, v in iteritems(self.view_data):
181
            if collecting:
182
                pass
183
            elif k == 'header_sort':
184
                collecting = True
185
            else:
186
                continue
187
            shortcuts.append(self.curse_add_line(v))
188
        # Divide shortcuts into 2 columns
189
        # and if number of schortcuts is even,
190
        # make the 1st column taller (len+1).
191
        #
192
        nlines = (len(shortcuts) + 1) // 2
193
        ret.extend(
194
            msg
195
            for triplet in zip(
196
                iter(shortcuts[:nlines]),
197
                chain(shortcuts[nlines:], iter(lambda: self.curse_add_line(''), None)),
198
                iter(self.curse_new_line, None),
199
            )
200
            for msg in triplet
201
        )
202
203
        ret.append(self.curse_new_line())
204
        ret.append(self.curse_add_line('For an exhaustive list of key bindings:'))
205
        ret.append(self.curse_new_line())
206
        ret.append(self.curse_add_line('https://glances.readthedocs.io/en/latest/cmds.html#interactive-commands'))
207
        ret.append(self.curse_new_line())
208
209
        ret.append(self.curse_new_line())
210
        ret.append(self.curse_add_line('Colors binding:'))
211
        ret.append(self.curse_new_line())
212
        for c in [
213
            'DEFAULT',
214
            'UNDERLINE',
215
            'BOLD',
216
            'SORT',
217
            'OK',
218
            'MAX',
219
            'FILTER',
220
            'TITLE',
221
            'PROCESS',
222
            'PROCESS_SELECTED',
223
            'STATUS',
224
            'NICE',
225
            'CPU_TIME',
226
            'CAREFUL',
227
            'WARNING',
228
            'CRITICAL',
229
            'OK_LOG',
230
            'CAREFUL_LOG',
231
            'WARNING_LOG',
232
            'CRITICAL_LOG',
233
            'PASSWORD',
234
            'SELECTED',
235
            'INFO',
236
            'ERROR',
237
            'SEPARATOR',
238
        ]:
239
            ret.append(self.curse_add_line(c, decoration=c))
240
            if c == 'CPU_TIME':
241
                ret.append(self.curse_new_line())
242
            else:
243
                ret.append(self.curse_add_line(' '))
244
245
        # Return the message with decoration
246
        return ret
247