_GlancesCurses.display()   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 113
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 55
nop 3
dl 0
loc 113
rs 2.4
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.outputs.glances_curses._GlancesCurses.display() 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 -*-
0 ignored issues
show
coding-style introduced by Nicolas Hennion
Too many lines in module (1068/1000)
Loading history...
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2019 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Curses interface class."""
21
from __future__ import unicode_literals
22
23
import re
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by Nicolas Hennion
The import re seems to be unused.
Loading history...
24
import sys
0 ignored issues
show
introduced by Alessio Sergi
import missing from __future__ import absolute_import
Loading history...
25
26
from glances.compat import to_ascii, nativestr, b, u, itervalues
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by Nicolas Hennion
Unused to_ascii imported from glances.compat
Loading history...
Unused Code introduced by Nicolas Hennion
Unused b imported from glances.compat
Loading history...
27
from glances.globals import MACOS, WINDOWS
0 ignored issues
show
introduced by Alessio Sergi
import missing from __future__ import absolute_import
Loading history...
28
from glances.logger import logger
0 ignored issues
show
introduced by Alessio Sergi
import missing from __future__ import absolute_import
Loading history...
29
from glances.events import glances_events
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
30
from glances.processes import glances_processes
0 ignored issues
show
introduced by Alessio Sergi
import missing from __future__ import absolute_import
Loading history...
31
from glances.timer import Timer
0 ignored issues
show
introduced by Alessio Sergi
import missing from __future__ import absolute_import
Loading history...
32
33
# Import curses library for "normal" operating system
34
if not WINDOWS:
35
    try:
36
        import curses
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
37
        import curses.panel
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
38
        from curses.textpad import Textbox
0 ignored issues
show
introduced by Nicolas Hennion
import missing from __future__ import absolute_import
Loading history...
39
    except ImportError:
40
        logger.critical("Curses module not found. Glances cannot start in standalone mode.")
0 ignored issues
show
Coding Style introduced by Alessio Sergi
This line is too long as per the coding-style (92/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
41
        sys.exit(1)
42
43
44
class _GlancesCurses(object):
0 ignored issues
show
best-practice introduced by Nicolas Hennion
Too many instance attributes (33/7)
Loading history...
best-practice introduced by Nicolas Hennion
Too many public methods (24/20)
Loading history...
45
46
    """This class manages the curses display (and key pressed).
47
48
    Note: It is a private class, use GlancesCursesClient or GlancesCursesBrowser.
0 ignored issues
show
Coding Style introduced by Alessio Sergi
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
49
    """
50
51
    _hotkeys = {
52
        '0': {'switch': 'disable_irix'},
53
        '1': {'switch': 'percpu'},
54
        '2': {'switch': 'disable_left_sidebar'},
55
        '3': {'switch': 'disable_quicklook'},
56
        '6': {'switch': 'meangpu'},
57
        '/': {'switch': 'process_short_name'},
58
        'A': {'switch': 'disable_amps'},
59
        'b': {'switch': 'byte'},
60
        'B': {'switch': 'diskio_iops'},
61
        'C': {'switch': 'disable_cloud'},
62
        'D': {'switch': 'disable_docker'},
63
        'd': {'switch': 'disable_diskio'},
64
        'F': {'switch': 'fs_free_space'},
65
        'g': {'switch': 'generate_graph'},
66
        'G': {'switch': 'disable_gpu'},
67
        'h': {'switch': 'help_tag'},
68
        'I': {'switch': 'disable_ip'},
69
        'k': {'switch': 'disable_connections'},
70
        'l': {'switch': 'disable_alert'},
71
        'M': {'switch': 'reset_minmax_tag'},
72
        'n': {'switch': 'disable_network'},
73
        'N': {'switch': 'disable_now'},
74
        'P': {'switch': 'disable_ports'},
75
        'Q': {'switch': 'enable_irq'},
76
        'R': {'switch': 'disable_raid'},
77
        's': {'switch': 'disable_sensors'},
78
        'S': {'switch': 'sparkline'},
79
        'T': {'switch': 'network_sum'},
80
        'U': {'switch': 'network_cumul'},
81
        'W': {'switch': 'disable_wifi'},
82
        # Processes sort hotkeys
83
        'a': {'auto_sort': True, 'sort_key': 'cpu_percent'},
84
        'c': {'auto_sort': False, 'sort_key': 'cpu_percent'},
85
        'i': {'auto_sort': False, 'sort_key': 'io_counters'},
86
        'm': {'auto_sort': False, 'sort_key': 'memory_percent'},
87
        'p': {'auto_sort': False, 'sort_key': 'name'},
88
        't': {'auto_sort': False, 'sort_key': 'cpu_times'},
89
        'u': {'auto_sort': False, 'sort_key': 'username'},
90
    }
91
92
    _sort_loop = ['cpu_percent', 'memory_percent', 'username',
93
                  'cpu_times', 'io_counters', 'name']
94
95
    # Define top menu
96
    _top = ['quicklook', 'cpu', 'percpu', 'gpu', 'mem', 'memswap', 'load']
97
    _quicklook_max_width = 68
98
99
    # Define left sidebar
100
    _left_sidebar = ['network', 'connections', 'wifi', 'ports', 'diskio', 'fs',
101
                     'irq', 'folders', 'raid', 'sensors', 'now']
102
    _left_sidebar_min_width = 23
103
    _left_sidebar_max_width = 34
104
105
    # Define right sidebar
106
    _right_sidebar = ['docker', 'processcount', 'amps', 'processlist', 'alert']
107
108
    def __init__(self, config=None, args=None):
109
        # Init
110
        self.config = config
111
        self.args = args
112
113
        # Init windows positions
114
        self.term_w = 80
115
        self.term_h = 24
116
117
        # Space between stats
118
        self.space_between_column = 3
119
        self.space_between_line = 2
120
121
        # Init the curses screen
122
        self.screen = curses.initscr()
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
123
        if not self.screen:
124
            logger.critical("Cannot init the curses library.\n")
125
            sys.exit(1)
126
127
        # Load the 'outputs' section of the configuration file
128
        # - Init the theme (default is black)
129
        self.theme = {'name': 'black'}
130
131
        # Load configuration file
132
        self.load_config(config)
133
134
        # Init cursor
135
        self._init_cursor()
136
137
        # Init the colors
138
        self._init_colors()
139
140
        # Init main window
141
        self.term_window = self.screen.subwin(0, 0)
142
143
        # Init edit filter tag
144
        self.edit_filter = False
145
146
        # Init the process min/max reset
147
        self.args.reset_minmax_tag = False
148
149
        # Catch key pressed with non blocking mode
150
        self.term_window.keypad(1)
151
        self.term_window.nodelay(1)
152
        self.pressedkey = -1
153
154
        # History tag
155
        self._init_history()
156
157
    def load_config(self, config):
158
        """Load the outputs section of the configuration file."""
159
        # Load the theme
160
        if config is not None and config.has_section('outputs'):
161
            logger.debug('Read the outputs section in the configuration file')
162
            self.theme['name'] = config.get_value('outputs', 'curse_theme', default='black')
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (92/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
163
            logger.debug('Theme for the curse interface: {}'.format(self.theme['name']))
0 ignored issues
show
Coding Style introduced by Alessio Sergi
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by Alessio Sergi
Use formatting in logging functions and pass the parameters as arguments
Loading history...
164
165
    def is_theme(self, name):
166
        """Return True if the theme *name* should be used."""
167
        return getattr(self.args, 'theme_' + name) or self.theme['name'] == name
168
169
    def _init_history(self):
170
        """Init the history option."""
171
172
        self.reset_history_tag = False
173
174
    def _init_cursor(self):
175
        """Init cursors."""
176
177
        if hasattr(curses, 'noecho'):
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
178
            curses.noecho()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named noecho.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
179
        if hasattr(curses, 'cbreak'):
180
            curses.cbreak()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named cbreak.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
181
        self.set_cursor(0)
182
183
    def _init_colors(self):
184
        """Init the Curses color layout."""
185
186
        # Set curses options
187
        try:
188
            if hasattr(curses, 'start_color'):
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
189
                curses.start_color()
190
            if hasattr(curses, 'use_default_colors'):
191
                curses.use_default_colors()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named use_default_colors.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
192
        except Exception as e:
0 ignored issues
show
Best Practice introduced by Nicolas Hennion
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style Naming introduced by Nicolas Hennion
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
193
            logger.warning('Error initializing terminal color ({})'.format(e))
0 ignored issues
show
introduced by Nicolas Hennion
Use formatting in logging functions and pass the parameters as arguments
Loading history...
194
195
        # Init colors
196
        if self.args.disable_bold:
197
            A_BOLD = 0
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name A_BOLD does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
198
            self.args.disable_bg = True
199
        else:
200
            A_BOLD = curses.A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Alessio Sergi
The name A_BOLD does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
201
202
        self.title_color = A_BOLD
203
        self.title_underline_color = A_BOLD | curses.A_UNDERLINE
204
        self.help_color = A_BOLD
205
206
        if curses.has_colors():
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named has_colors.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
207
            # The screen is compatible with a colored design
208
            if self.is_theme('white'):
209
                # White theme: black ==> white
210
                curses.init_pair(1, curses.COLOR_BLACK, -1)
0 ignored issues
show
Bug introduced by dana
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
211
            else:
212
                curses.init_pair(1, curses.COLOR_WHITE, -1)
0 ignored issues
show
Bug introduced by dana
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
213
            if self.args.disable_bg:
214
                curses.init_pair(2, curses.COLOR_RED, -1)
0 ignored issues
show
Bug introduced by dana
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
215
                curses.init_pair(3, curses.COLOR_GREEN, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
216
                curses.init_pair(4, curses.COLOR_BLUE, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
217
                curses.init_pair(5, curses.COLOR_MAGENTA, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
218
            else:
219
                curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
0 ignored issues
show
Bug introduced by Alessio Sergi
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
220
                curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_GREEN)
0 ignored issues
show
Bug introduced by Alessio Sergi
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
221
                curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_BLUE)
0 ignored issues
show
Bug introduced by Alessio Sergi
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
222
                curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
0 ignored issues
show
Bug introduced by Alessio Sergi
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
223
            curses.init_pair(6, curses.COLOR_RED, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
224
            curses.init_pair(7, curses.COLOR_GREEN, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
225
            curses.init_pair(8, curses.COLOR_BLUE, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
226
227
            # Colors text styles
228
            if curses.COLOR_PAIRS > 8:
229
                try:
230
                    curses.init_pair(9, curses.COLOR_MAGENTA, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
231
                except Exception:
0 ignored issues
show
Best Practice introduced by Nicolas Hennion
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
232
                    if self.is_theme('white'):
233
                        curses.init_pair(9, curses.COLOR_BLACK, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
234
                    else:
235
                        curses.init_pair(9, curses.COLOR_WHITE, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
236
                try:
237
                    curses.init_pair(10, curses.COLOR_CYAN, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
238
                except Exception:
0 ignored issues
show
Best Practice introduced by Nicolas Hennion
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
239
                    if self.is_theme('white'):
240
                        curses.init_pair(10, curses.COLOR_BLACK, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
241
                    else:
242
                        curses.init_pair(10, curses.COLOR_WHITE, -1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named init_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
243
244
                self.ifWARNING_color2 = curses.color_pair(9) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name ifWARNING_color2 does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
245
                self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name ifCRITICAL_color2 does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
246
                self.filter_color = curses.color_pair(10) | A_BOLD
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
247
248
            self.no_color = curses.color_pair(1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
249
            self.default_color = curses.color_pair(3) | A_BOLD
0 ignored issues
show
Bug introduced by Alessio Sergi
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
250
            self.nice_color = curses.color_pair(9)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
251
            self.cpu_time_color = curses.color_pair(9)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
252
            self.ifCAREFUL_color = curses.color_pair(4) | A_BOLD
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Coding Style Naming introduced by Nicolas Hennion
The name ifCAREFUL_color does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
253
            self.ifWARNING_color = curses.color_pair(5) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name ifWARNING_color does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
254
            self.ifCRITICAL_color = curses.color_pair(2) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name ifCRITICAL_color does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
255
            self.default_color2 = curses.color_pair(7)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
256
            self.ifCAREFUL_color2 = curses.color_pair(8) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name ifCAREFUL_color2 does not conform to the attribute naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named color_pair.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
257
258
        else:
259
            # The screen is NOT compatible with a colored design
260
            # switch to B&W text styles
261
            self.no_color = curses.A_NORMAL
262
            self.default_color = curses.A_NORMAL
263
            self.nice_color = A_BOLD
264
            self.cpu_time_color = A_BOLD
265
            self.ifCAREFUL_color = curses.A_UNDERLINE
266
            self.ifWARNING_color = A_BOLD
267
            self.ifCRITICAL_color = curses.A_REVERSE
268
            self.default_color2 = curses.A_NORMAL
269
            self.ifCAREFUL_color2 = curses.A_UNDERLINE
270
            self.ifWARNING_color2 = A_BOLD
271
            self.ifCRITICAL_color2 = curses.A_REVERSE
272
            self.filter_color = A_BOLD
273
274
        # Define the colors list (hash table) for stats
275
        self.colors_list = {
276
            'DEFAULT': self.no_color,
277
            'UNDERLINE': curses.A_UNDERLINE,
278
            'BOLD': A_BOLD,
279
            'SORT': A_BOLD,
280
            'OK': self.default_color2,
281
            'MAX': self.default_color2 | curses.A_BOLD,
282
            'FILTER': self.filter_color,
283
            'TITLE': self.title_color,
284
            'PROCESS': self.default_color2,
285
            'STATUS': self.default_color2,
286
            'NICE': self.nice_color,
287
            'CPU_TIME': self.cpu_time_color,
288
            'CAREFUL': self.ifCAREFUL_color2,
289
            'WARNING': self.ifWARNING_color2,
290
            'CRITICAL': self.ifCRITICAL_color2,
291
            'OK_LOG': self.default_color,
292
            'CAREFUL_LOG': self.ifCAREFUL_color,
293
            'WARNING_LOG': self.ifWARNING_color,
294
            'CRITICAL_LOG': self.ifCRITICAL_color,
295
            'PASSWORD': curses.A_PROTECT
296
        }
297
298
    def set_cursor(self, value):
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
299
        """Configure the curse cursor apparence.
300
301
        0: invisible
302
        1: visible
303
        2: very visible
304
        """
305
        if hasattr(curses, 'curs_set'):
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
306
            try:
307
                curses.curs_set(value)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named curs_set.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
308
            except Exception:
0 ignored issues
show
Best Practice introduced by Nicolas Hennion
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
309
                pass
310
311
    # def get_key(self, window):
312
    #     # Catch ESC key AND numlock key (issue #163)
313
    #     keycode = [0, 0]
314
    #     keycode[0] = window.getch()
315
    #     keycode[1] = window.getch()
316
    #
317
    #     if keycode != [-1, -1]:
318
    #         logger.debug("Keypressed (code: %s)" % keycode)
319
    #
320
    #     if keycode[0] == 27 and keycode[1] != -1:
321
    #         # Do not escape on specials keys
322
    #         return -1
323
    #     else:
324
    #         return keycode[0]
325
326
    def get_key(self, window):
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Coding Style introduced by Nicolas Hennion
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
327
        # @TODO: Check issue #163
328
        ret = window.getch()
329
        logger.debug("Keypressed (code: %s)" % ret)
0 ignored issues
show
Coding Style Best Practice introduced by Nicolas Hennion
Specify string format arguments as logging function parameters
Loading history...
330
        return ret
331
332
    def __catch_key(self, return_to_browser=False):
333
        # Catch the pressed key
334
        self.pressedkey = self.get_key(self.term_window)
335
336
        # Actions (available in the global hotkey dict)...
337
        for hotkey in self._hotkeys:
338
            if self.pressedkey == ord(hotkey) and 'switch' in self._hotkeys[hotkey]:
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
339
                setattr(self.args,
340
                        self._hotkeys[hotkey]['switch'],
341
                        not getattr(self.args,
342
                                    self._hotkeys[hotkey]['switch']))
343
            if self.pressedkey == ord(hotkey) and 'auto_sort' in self._hotkeys[hotkey]:
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (87/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
344
                setattr(glances_processes,
345
                        'auto_sort',
346
                        self._hotkeys[hotkey]['auto_sort'])
347
            if self.pressedkey == ord(hotkey) and 'sort_key' in self._hotkeys[hotkey]:
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (86/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
348
                setattr(glances_processes,
349
                        'sort_key',
350
                        self._hotkeys[hotkey]['sort_key'])
351
352
        # Other actions...
353
        if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
354
            # 'ESC'|'q' > Quit
355
            if return_to_browser:
356
                logger.info("Stop Glances client and return to the browser")
357
            else:
358
                logger.info("Stop Glances (keypressed: {})".format(self.pressedkey))
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by Nicolas Hennion
Use formatting in logging functions and pass the parameters as arguments
Loading history...
359
        elif self.pressedkey == ord('\n'):
360
            # 'ENTER' > Edit the process filter
361
            self.edit_filter = not self.edit_filter
362
        elif self.pressedkey == ord('4'):
363
            self.args.full_quicklook = not self.args.full_quicklook
364
            if self.args.full_quicklook:
365
                self.enable_fullquicklook()
366
            else:
367
                self.disable_fullquicklook()
368
        elif self.pressedkey == ord('5'):
369
            self.args.disable_top = not self.args.disable_top
370
            if self.args.disable_top:
371
                self.disable_top()
372
            else:
373
                self.enable_top()
374
        elif self.pressedkey == ord('e'):
375
            # 'e' > Enable/Disable process extended
376
            self.args.enable_process_extended = not self.args.enable_process_extended
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This line is too long as per the coding-style (85/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
377
            if not self.args.enable_process_extended:
378
                glances_processes.disable_extended()
379
            else:
380
                glances_processes.enable_extended()
381
        elif self.pressedkey == ord('E'):
382
            # 'E' > Erase the process filter
383
            glances_processes.process_filter = None
384
        elif self.pressedkey == ord('f'):
385
            # 'f' > Show/hide fs / folder stats
386
            self.args.disable_fs = not self.args.disable_fs
387
            self.args.disable_folders = not self.args.disable_folders
388
        elif self.pressedkey == ord('w'):
389
            # 'w' > Delete finished warning logs
390
            glances_events.clean()
391
        elif self.pressedkey == ord('x'):
392
            # 'x' > Delete finished warning and critical logs
393
            glances_events.clean(critical=True)
394
        elif self.pressedkey == ord('z'):
395
            # 'z' > Enable or disable processes
396
            self.args.disable_process = not self.args.disable_process
397
            if self.args.disable_process:
398
                glances_processes.disable()
399
            else:
400
                glances_processes.enable()
401
        elif self.pressedkey == curses.KEY_LEFT:
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
402
            # "<" (left arrow) navigation through process sort
403
            setattr(glances_processes, 'auto_sort', False)
404
            next_sort = (self.loop_position() - 1) % len(self._sort_loop)
405
            glances_processes.sort_key = self._sort_loop[next_sort]
406
        elif self.pressedkey == curses.KEY_RIGHT:
407
            # ">" (right arrow) navigation through process sort
408
            setattr(glances_processes, 'auto_sort', False)
409
            next_sort = (self.loop_position() + 1) % len(self._sort_loop)
410
            glances_processes.sort_key = self._sort_loop[next_sort]
411
412
        # Return the key code
413
        return self.pressedkey
414
415
    def loop_position(self):
416
        """Return the current sort in the loop"""
417
        for i, v in enumerate(self._sort_loop):
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name v does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
418
            if v == glances_processes.sort_key:
419
                return i
420
        return 0
421
422
    def disable_top(self):
423
        """Disable the top panel"""
424
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap', 'load']:
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name p does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
425
            setattr(self.args, 'disable_' + p, True)
426
427
    def enable_top(self):
428
        """Enable the top panel"""
429
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap', 'load']:
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name p does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
430
            setattr(self.args, 'disable_' + p, False)
431
432
    def disable_fullquicklook(self):
433
        """Disable the full quicklook mode"""
434
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap']:
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name p does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
435
            setattr(self.args, 'disable_' + p, False)
436
437
    def enable_fullquicklook(self):
438
        """Disable the full quicklook mode"""
439
        self.args.disable_quicklook = False
440
        for p in ['cpu', 'gpu', 'mem', 'memswap']:
0 ignored issues
show
Coding Style Naming introduced by Nicolas Hennion
The name p does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
441
            setattr(self.args, 'disable_' + p, True)
442
443
    def end(self):
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
444
        """Shutdown the curses window."""
445
        if hasattr(curses, 'echo'):
0 ignored issues
show
introduced by Nicolas Hennion
The variable curses does not seem to be defined in case BooleanNotNode on line 34 is False. Are you sure this can never be the case?
Loading history...
446
            curses.echo()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named echo.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
447
        if hasattr(curses, 'nocbreak'):
448
            curses.nocbreak()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named nocbreak.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
449
        if hasattr(curses, 'curs_set'):
450
            try:
451
                curses.curs_set(1)
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named curs_set.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
452
            except Exception:
0 ignored issues
show
Best Practice introduced by Nicolas Hennion
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
453
                pass
454
        curses.endwin()
0 ignored issues
show
Bug introduced by Nicolas Hennion
The Module curses does not seem to have a member named endwin.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
455
456
    def init_line_column(self):
457
        """Init the line and column position for the curses interface."""
458
        self.init_line()
459
        self.init_column()
460
461
    def init_line(self):
462
        """Init the line position for the curses interface."""
463
        self.line = 0
0 ignored issues
show
Coding Style introduced by Nicolas Hennion
The attribute line was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
464
        self.next_line = 0
0 ignored issues
show