Passed
Push — master ( cdb6bf...0d35d5 )
by Nicolas
04:08 queued 14s
created

GlancesTextboxYesNo.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 3
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
0 ignored issues
show
coding-style introduced by
Too many lines in module (1157/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
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
The import re seems to be unused.
Loading history...
24
import sys
0 ignored issues
show
introduced by
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
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
Unused to_ascii imported from glances.compat
Loading history...
Unused Code introduced by
Unused b imported from glances.compat
Loading history...
27
from glances.globals import MACOS, WINDOWS
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
28
from glances.logger import logger
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
29
from glances.events import glances_events
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
30
from glances.processes import glances_processes
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
31
from glances.timer import Timer
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
32
33
# Import curses library for "normal" operating system
34
try:
35
    import curses
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
36
    import curses.panel
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
37
    from curses.textpad import Textbox
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
38
except ImportError:
39
    logger.critical("Curses module not found. Glances cannot start in standalone mode.")
0 ignored issues
show
Coding Style introduced by
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...
40
    if WINDOWS:
41
	    logger.critical("For Windows you can try installing windows-curses with pip install.")
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

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

Loading history...
42
    sys.exit(1)
43
44
45
class _GlancesCurses(object):
0 ignored issues
show
best-practice introduced by
Too many public methods (24/20)
Loading history...
best-practice introduced by
Too many instance attributes (35/7)
Loading history...
46
47
    """This class manages the curses display (and key pressed).
48
49
    Note: It is a private class, use GlancesCursesClient or GlancesCursesBrowser.
0 ignored issues
show
Coding Style introduced by
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...
50
    """
51
52
    _hotkeys = {
53
        # 'ENTER' > Edit the process filter
54
        '0': {'switch': 'disable_irix'},
55
        '1': {'switch': 'percpu'},
56
        '2': {'switch': 'disable_left_sidebar'},
57
        '3': {'switch': 'disable_quicklook'},
58
        # '4' > Enable or disable quicklook
59
        # '5' > Enable or disable top menu
60
        '6': {'switch': 'meangpu'},
61
        '/': {'switch': 'process_short_name'},
62
        'a': {'sort_key': 'auto'},
63
        'A': {'switch': 'disable_amps'},
64
        'b': {'switch': 'byte'},
65
        'B': {'switch': 'diskio_iops'},
66
        'c': {'sort_key': 'cpu_percent'},
67
        'C': {'switch': 'disable_cloud'},
68
        'd': {'switch': 'disable_diskio'},
69
        'D': {'switch': 'disable_docker'},
70
        # 'e' > Enable/Disable process extended
71
        # 'E' > Erase the process filter
72
        # 'f' > Show/hide fs / folder stats
73
        'F': {'switch': 'fs_free_space'},
74
        'g': {'switch': 'generate_graph'},
75
        'G': {'switch': 'disable_gpu'},
76
        'h': {'switch': 'help_tag'},
77
        'i': {'sort_key': 'io_counters'},
78
        'I': {'switch': 'disable_ip'},
79
        # 'k' > Kill selected process
80
        'K': {'switch': 'disable_connections'},
81
        'l': {'switch': 'disable_alert'},
82
        'm': {'sort_key': 'memory_percent'},
83
        'M': {'switch': 'reset_minmax_tag'},
84
        'n': {'switch': 'disable_network'},
85
        'N': {'switch': 'disable_now'},
86
        'p': {'sort_key': 'name'},
87
        'P': {'switch': 'disable_ports'},
88
        # 'q' or ESCAPE > Quit
89
        'Q': {'switch': 'enable_irq'},
90
        'r': {'switch': 'disable_smart'},
91
        'R': {'switch': 'disable_raid'},
92
        's': {'switch': 'disable_sensors'},
93
        'S': {'switch': 'sparkline'},
94
        't': {'sort_key': 'cpu_times'},
95
        'T': {'switch': 'network_sum'},
96
        'u': {'sort_key': 'username'},
97
        'U': {'switch': 'network_cumul'},
98
        # 'w' > Delete finished warning logs
99
        'W': {'switch': 'disable_wifi'},
100
        # 'x' > Delete finished warning and critical logs
101
        # 'z' > Enable or disable processes
102
        # "<" (left arrow) navigation through process sort
103
        # ">" (right arrow) navigation through process sort
104
        # 'UP' > Up in the server list
105
        # 'DOWN' > Down in the server list    
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
106
    }
107
108
    _sort_loop = ['cpu_percent', 'memory_percent', 'username',
109
                  'cpu_times', 'io_counters', 'name']
110
111
    # Define top menu
112
    _top = ['quicklook', 'cpu', 'percpu', 'gpu', 'mem', 'memswap', 'load']
113
    _quicklook_max_width = 68
114
115
    # Define left sidebar
116
    _left_sidebar = ['network', 'connections', 'wifi', 'ports', 'diskio', 'fs',
117
                     'irq', 'folders', 'raid', 'smart', 'sensors', 'now']
118
    _left_sidebar_min_width = 23
119
    _left_sidebar_max_width = 34
120
121
    # Define right sidebar
122
    _right_sidebar = ['docker', 'processcount', 'amps', 'processlist', 'alert']
123
124
    def __init__(self, config=None, args=None):
125
        # Init
126
        self.config = config
127
        self.args = args
128
129
        # Init windows positions
130
        self.term_w = 80
131
        self.term_h = 24
132
133
        # Space between stats
134
        self.space_between_column = 3
135
        self.space_between_line = 2
136
137
        # Init the curses screen
138
        self.screen = curses.initscr()
139
        if not self.screen:
140
            logger.critical("Cannot init the curses library.\n")
141
            sys.exit(1)
142
143
        # Load the 'outputs' section of the configuration file
144
        # - Init the theme (default is black)
145
        self.theme = {'name': 'black'}
146
147
        # Load configuration file
148
        self.load_config(config)
149
150
        # Init cursor
151
        self._init_cursor()
152
153
        # Init the colors
154
        self._init_colors()
155
156
        # Init main window
157
        self.term_window = self.screen.subwin(0, 0)
158
159
        # Init edit filter tag
160
        self.edit_filter = False
161
162
        # Init kill process tag
163
        self.kill_process = False
164
165
        # Init the process min/max reset
166
        self.args.reset_minmax_tag = False
167
168
        # Init cursor
169
        self.args.cursor_position = 0
170
171
        # Catch key pressed with non blocking mode
172
        self.term_window.keypad(1)
173
        self.term_window.nodelay(1)
174
        self.pressedkey = -1
175
176
        # History tag
177
        self._init_history()
178
179
    def load_config(self, config):
180
        """Load the outputs section of the configuration file."""
181
        # Load the theme
182
        if config is not None and config.has_section('outputs'):
183
            logger.debug('Read the outputs section in the configuration file')
184
            self.theme['name'] = config.get_value('outputs', 'curse_theme', default='black')
0 ignored issues
show
Coding Style introduced by
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...
185
            logger.debug('Theme for the curse interface: {}'.format(self.theme['name']))
0 ignored issues
show
Coding Style introduced by
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
Use formatting in logging functions and pass the parameters as arguments
Loading history...
186
187
    def is_theme(self, name):
188
        """Return True if the theme *name* should be used."""
189
        return getattr(self.args, 'theme_' + name) or self.theme['name'] == name
190
191
    def _init_history(self):
192
        """Init the history option."""
193
194
        self.reset_history_tag = False
195
196
    def _init_cursor(self):
197
        """Init cursors."""
198
199
        if hasattr(curses, 'noecho'):
200
            curses.noecho()
0 ignored issues
show
Bug introduced by
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...
201
        if hasattr(curses, 'cbreak'):
202
            curses.cbreak()
0 ignored issues
show
Bug introduced by
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...
203
        self.set_cursor(0)
204
205
    def _init_colors(self):
206
        """Init the Curses color layout."""
207
208
        # Set curses options
209
        try:
210
            if hasattr(curses, 'start_color'):
211
                curses.start_color()
212
                logger.debug(
213
                    'Curses interface compatible with {} colors'.format(curses.COLORS))
0 ignored issues
show
Coding Style introduced by
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...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
214
            if hasattr(curses, 'use_default_colors'):
215
                curses.use_default_colors()
0 ignored issues
show
Bug introduced by
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...
216
        except Exception as e:
0 ignored issues
show
Best Practice introduced by
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
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...
217
            logger.warning('Error initializing terminal color ({})'.format(e))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
218
219
        # Init colors
220
        if self.args.disable_bold:
221
            A_BOLD = 0
0 ignored issues
show
Coding Style Naming introduced by
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...
222
            self.args.disable_bg = True
223
        else:
224
            A_BOLD = curses.A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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...
225
226
        self.title_color = A_BOLD
227
        self.title_underline_color = A_BOLD | curses.A_UNDERLINE
228
        self.help_color = A_BOLD
229
230
        if curses.has_colors():
0 ignored issues
show
Bug introduced by
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...
231
            # The screen is compatible with a colored design
232
            if self.is_theme('white'):
233
                # White theme: black ==> white
234
                curses.init_pair(1, curses.COLOR_BLACK, -1)
0 ignored issues
show
Bug introduced by
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...
235
            else:
236
                curses.init_pair(1, curses.COLOR_WHITE, -1)
0 ignored issues
show
Bug introduced by
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...
237
            if self.args.disable_bg:
238
                curses.init_pair(2, curses.COLOR_RED, -1)
0 ignored issues
show
Bug introduced by
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...
239
                curses.init_pair(3, curses.COLOR_GREEN, -1)
0 ignored issues
show
Bug introduced by
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...
240
                curses.init_pair(4, curses.COLOR_BLUE, -1)
0 ignored issues
show
Bug introduced by
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
                curses.init_pair(5, curses.COLOR_MAGENTA, -1)
0 ignored issues
show
Bug introduced by
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...
242
            else:
243
                curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
0 ignored issues
show
Bug introduced by
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...
244
                curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_GREEN)
0 ignored issues
show
Bug introduced by
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...
245
                curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_BLUE)
0 ignored issues
show
Bug introduced by
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...
246
                curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
0 ignored issues
show
Bug introduced by
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...
247
            curses.init_pair(6, curses.COLOR_RED, -1)
0 ignored issues
show
Bug introduced by
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...
248
            curses.init_pair(7, curses.COLOR_GREEN, -1)
0 ignored issues
show
Bug introduced by
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...
249
            curses.init_pair(8, curses.COLOR_BLUE, -1)
0 ignored issues
show
Bug introduced by
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...
250
251
            # Colors text styles
252
            self.no_color = curses.color_pair(1)
0 ignored issues
show
Bug introduced by
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...
253
            self.default_color = curses.color_pair(3) | A_BOLD
0 ignored issues
show
Bug introduced by
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.nice_color = curses.color_pair(5)
0 ignored issues
show
Bug introduced by
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.cpu_time_color = curses.color_pair(5)
0 ignored issues
show
Bug introduced by
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_color = curses.color_pair(4) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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...
Bug introduced by
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
            self.ifWARNING_color = curses.color_pair(5) | A_BOLD
0 ignored issues
show
Bug introduced by
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
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...
258
            self.ifCRITICAL_color = curses.color_pair(2) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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
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...
259
            self.default_color2 = curses.color_pair(7)
0 ignored issues
show
Bug introduced by
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...
260
            self.ifCAREFUL_color2 = curses.color_pair(8) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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
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...
261
            self.ifWARNING_color2 = curses.color_pair(5) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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
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...
262
            self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
0 ignored issues
show
Coding Style Naming introduced by
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
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...
263
            self.filter_color = A_BOLD
264
            self.selected_color = A_BOLD
265
266
            if curses.COLOR_PAIRS > 8:
267
                colors_list = [curses.COLOR_MAGENTA, curses.COLOR_CYAN, curses.COLOR_YELLOW]
0 ignored issues
show
Coding Style introduced by
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...
268
                for i in range(0, 3):
269
                    try:
270
                        curses.init_pair(i + 9, colors_list[i], -1)
0 ignored issues
show
Bug introduced by
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...
271
                    except Exception:
0 ignored issues
show
Best Practice introduced by
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...
272
                        if self.is_theme('white'):
273
                            curses.init_pair(i + 9, curses.COLOR_BLACK, -1)
0 ignored issues
show
Bug introduced by
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...
274
                        else:
275
                            curses.init_pair(i + 9, curses.COLOR_WHITE, -1)
0 ignored issues
show
Bug introduced by
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...
276
                self.nice_color = curses.color_pair(9)
0 ignored issues
show
Bug introduced by
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...
277
                self.cpu_time_color = curses.color_pair(9)
0 ignored issues
show
Bug introduced by
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...
278
                self.ifWARNING_color2 = curses.color_pair(9) | A_BOLD
0 ignored issues
show
Bug introduced by
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...
279
                self.filter_color = curses.color_pair(10) | A_BOLD
0 ignored issues
show
Bug introduced by
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...
280
                self.selected_color = curses.color_pair(11) | A_BOLD
0 ignored issues
show
Bug introduced by
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...
281
282
        else:
283
            # The screen is NOT compatible with a colored design
284
            # switch to B&W text styles
285
            self.no_color = curses.A_NORMAL
286
            self.default_color = curses.A_NORMAL
287
            self.nice_color = A_BOLD
288
            self.cpu_time_color = A_BOLD
289
            self.ifCAREFUL_color = curses.A_UNDERLINE
290
            self.ifWARNING_color = A_BOLD
291
            self.ifCRITICAL_color = curses.A_REVERSE
292
            self.default_color2 = curses.A_NORMAL
293
            self.ifCAREFUL_color2 = curses.A_UNDERLINE
294
            self.ifWARNING_color2 = A_BOLD
295
            self.ifCRITICAL_color2 = curses.A_REVERSE
296
            self.filter_color = A_BOLD
297
            self.selected_color = A_BOLD
298
299
        # Define the colors list (hash table) for stats
300
        self.colors_list = {
301
            'DEFAULT': self.no_color,
302
            'UNDERLINE': curses.A_UNDERLINE,
303
            'BOLD': A_BOLD,
304
            'SORT': curses.A_UNDERLINE | A_BOLD,
305
            'OK': self.default_color2,
306
            'MAX': self.default_color2 | A_BOLD,
307
            'FILTER': self.filter_color,
308
            'TITLE': self.title_color,
309
            'PROCESS': self.default_color2,
310
            'PROCESS_SELECTED': self.default_color2 | curses.A_UNDERLINE,
311
            'STATUS': self.default_color2,
312
            'NICE': self.nice_color,
313
            'CPU_TIME': self.cpu_time_color,
314
            'CAREFUL': self.ifCAREFUL_color2,
315
            'WARNING': self.ifWARNING_color2,
316
            'CRITICAL': self.ifCRITICAL_color2,
317
            'OK_LOG': self.default_color,
318
            'CAREFUL_LOG': self.ifCAREFUL_color,
319
            'WARNING_LOG': self.ifWARNING_color,
320
            'CRITICAL_LOG': self.ifCRITICAL_color,
321
            'PASSWORD': curses.A_PROTECT,
322
            'SELECTED': self.selected_color
323
        }
324
325
    def set_cursor(self, value):
0 ignored issues
show
Coding Style introduced by
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...
326
        """Configure the curse cursor apparence.
327
328
        0: invisible
329
        1: visible
330
        2: very visible
331
        """
332
        if hasattr(curses, 'curs_set'):
333
            try:
334
                curses.curs_set(value)
0 ignored issues
show
Bug introduced by
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...
335
            except Exception:
0 ignored issues
show
Best Practice introduced by
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...
336
                pass
337
338
    def get_key(self, window):
0 ignored issues
show
Coding Style introduced by
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
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...
339
        # @TODO: Check issue #163
340
        ret = window.getch()
341
        logger.debug("Keypressed (code: %s)" % ret)
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
342
        return ret
343
344
    def __catch_key(self, return_to_browser=False):
345
        # Catch the pressed key
346
        self.pressedkey = self.get_key(self.term_window)
347
348
        # Actions (available in the global hotkey dict)...
349
        for hotkey in self._hotkeys:
350
            if self.pressedkey == ord(hotkey) and 'switch' in self._hotkeys[hotkey]:
0 ignored issues
show
Coding Style introduced by
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...
351
                setattr(self.args,
352
                        self._hotkeys[hotkey]['switch'],
353
                        not getattr(self.args,
354
                                    self._hotkeys[hotkey]['switch']))
355
            if self.pressedkey == ord(hotkey) and 'sort_key' in self._hotkeys[hotkey]:
0 ignored issues
show
Coding Style introduced by
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...
356
                glances_processes.set_sort_key(self._hotkeys[hotkey]['sort_key'],
0 ignored issues
show
Coding Style introduced by
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...
357
                                               self._hotkeys[hotkey]['sort_key'] == 'auto')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

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

Loading history...
358
359
        # Other actions...
360
        if self.pressedkey == ord('\n'):
361
            # 'ENTER' > Edit the process filter
362
            self.edit_filter = not self.edit_filter
363
        elif self.pressedkey == ord('4'):
364
            # '4' > Enable or disable quicklook
365
            self.args.full_quicklook = not self.args.full_quicklook
366
            if self.args.full_quicklook:
367
                self.enable_fullquicklook()
368
            else:
369
                self.disable_fullquicklook()
370
        elif self.pressedkey == ord('5'):
371
            # '5' > Enable or disable top menu
372
            self.args.disable_top = not self.args.disable_top
373
            if self.args.disable_top:
374
                self.disable_top()
375
            else:
376
                self.enable_top()
377
        elif self.pressedkey == ord('e'):
378
            # 'e' > Enable/Disable process extended
379
            self.args.enable_process_extended = not self.args.enable_process_extended
0 ignored issues
show
Coding Style introduced by
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...
380
            if not self.args.enable_process_extended:
381
                glances_processes.disable_extended()
382
            else:
383
                glances_processes.enable_extended()
384
        elif self.pressedkey == ord('E'):
385
            # 'E' > Erase the process filter
386
            glances_processes.process_filter = None
387
        elif self.pressedkey == ord('f'):
388
            # 'f' > Show/hide fs / folder stats
389
            self.args.disable_fs = not self.args.disable_fs
390
            self.args.disable_folders = not self.args.disable_folders
391
        elif self.pressedkey == ord('k'):
392
            # 'k' > Kill selected process (after confirmation)
393
            self.kill_process = not self.kill_process
394
        elif self.pressedkey == ord('w'):
395
            # 'w' > Delete finished warning logs
396
            glances_events.clean()
397
        elif self.pressedkey == ord('x'):
398
            # 'x' > Delete finished warning and critical logs
399
            glances_events.clean(critical=True)
400
        elif self.pressedkey == ord('z'):
401
            # 'z' > Enable or disable processes
402
            self.args.disable_process = not self.args.disable_process
403
            if self.args.disable_process:
404
                glances_processes.disable()
405
            else:
406
                glances_processes.enable()
407
        elif self.pressedkey == curses.KEY_LEFT:
408
            # "<" (left arrow) navigation through process sort
409
            next_sort = (self.loop_position() - 1) % len(self._sort_loop)
410
            glances_processes.set_sort_key(self._sort_loop[next_sort], False)
411
        elif self.pressedkey == curses.KEY_RIGHT:
412
            # ">" (right arrow) navigation through process sort
413
            next_sort = (self.loop_position() + 1) % len(self._sort_loop)
414
            glances_processes.set_sort_key(self._sort_loop[next_sort], False)
415
        elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
416
            # 'UP' > Up in the server list
417
            if self.args.cursor_position > 0:
418
                self.args.cursor_position -= 1
419
        elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
420
            # 'DOWN' > Down in the server list
421
            # if self.args.cursor_position < glances_processes.max_processes - 2:
0 ignored issues
show
Coding Style introduced by
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...
422
            if self.args.cursor_position < glances_processes.processes_count:
423
                self.args.cursor_position += 1
424
        elif self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
425
            # 'ESC'|'q' > Quit
426
            if return_to_browser:
427
                logger.info("Stop Glances client and return to the browser")
428
            else:
429
                logger.info(
430
                    "Stop Glances (keypressed: {})".format(self.pressedkey))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
431
        elif self.pressedkey == curses.KEY_F5:
0 ignored issues
show
Bug introduced by
Module 'curses' has no 'KEY_F5' member; maybe 'KEY_F0'?

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...
432
            # "F5" manual refresh requested
433
            pass
434
435
        # Return the key code
436
        return self.pressedkey
437
438
    def loop_position(self):
439
        """Return the current sort in the loop"""
440
        for i, v in enumerate(self._sort_loop):
0 ignored issues
show
Coding Style Naming introduced by
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...
441
            if v == glances_processes.sort_key:
442
                return i
443
        return 0
444
445
    def disable_top(self):
446
        """Disable the top panel"""
447
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap', 'load']:
0 ignored issues
show
Coding Style Naming introduced by
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...
448
            setattr(self.args, 'disable_' + p, True)
449
450
    def enable_top(self):
451
        """Enable the top panel"""
452
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap', 'load']:
0 ignored issues
show
Coding Style Naming introduced by
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...
453
            setattr(self.args, 'disable_' + p, False)
454
455
    def disable_fullquicklook(self):
456
        """Disable the full quicklook mode"""
457
        for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap']:
0 ignored issues
show
Coding Style Naming introduced by
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...
458
            setattr(self.args, 'disable_' + p, False)
459
460
    def enable_fullquicklook(self):
461
        """Disable the full quicklook mode"""
462
        self.args.disable_quicklook = False
463
        for p in ['cpu', 'gpu', 'mem', 'memswap']:
0 ignored issues
show
Coding Style Naming introduced by
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...
464
            setattr(self.args, 'disable_' + p, True)
465
466
    def end(self):
0 ignored issues
show
Coding Style introduced by
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...
467
        """Shutdown the curses window."""
468
        if hasattr(curses, 'echo'):
469
            curses.echo()
0 ignored issues
show
Bug introduced by
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...
470
        if hasattr(curses, 'nocbreak'):
471
            curses.nocbreak()
0 ignored issues
show
Bug introduced by
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...
472
        if hasattr(curses, 'curs_set'):
473
            try:
474
                curses.curs_set(1)
0 ignored issues
show
Bug introduced by
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...
475
            except Exception:
0 ignored issues
show
Best Practice introduced by
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...
476
                pass
477
        curses.endwin()
0 ignored issues
show
Bug introduced by
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...
478
479
    def init_line_column(self):
480
        """Init the line and column position for the curses interface."""
481
        self.init_line()
482
        self.init_column()
483
484
    def init_line(self):
485
        """Init the line position for the curses interface."""
486
        self.line = 0
0 ignored issues
show
Coding Style introduced by
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...
487
        self.next_line = 0
0 ignored issues
show
Coding Style introduced by
The attribute next_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...
488
489
    def init_column(self):
490
        """Init the column position for the curses interface."""
491
        self.column = 0
0 ignored issues
show
Coding Style introduced by
The attribute column 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...
492
        self.next_column = 0
0 ignored issues
show
Coding Style introduced by
The attribute next_column 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...
493
494
    def new_line(self):
495
        """New line in the curses interface."""
496
        self.line = self.next_line
0 ignored issues
show
Coding Style introduced by
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...
497
498
    def new_column(self):
499
        """New column in the curses interface."""
500
        self.column = self.next_column
0 ignored issues
show
Coding Style introduced by
The attribute column 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...
501
502
    def __get_stat_display(self, stats, layer):
0 ignored issues
show
Unused Code introduced by
The argument layer seems to be unused.
Loading history...
503
        """Return a dict of dict with all the stats display.
504
        stats: Global stats dict
505
        layer: ~ cs_status
506
            "None": standalone or server mode
507
            "Connected": Client is connected to a Glances server
508
            "SNMP": Client is connected to a SNMP server
509
            "Disconnected": Client is disconnected from the server
510
511
        :returns: dict of dict
512
            * key: plugin name
513
            * value: dict returned by the get_stats_display Plugin method
514
        """
515
        ret = {}
516
517
        for p in stats.getPluginsList(enable=False):
0 ignored issues
show
Coding Style Naming introduced by
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...
518
            if p == 'quicklook' or p == 'processlist':
519
                # processlist is done later
520
                # because we need to know how many processes could be displayed
521
                continue
522
523
            # Compute the plugin max size
524
            plugin_max_width = None
525
            if p in self._left_sidebar:
526
                plugin_max_width = max(self._left_sidebar_min_width,
527
                                       self.term_window.getmaxyx()[1] - 105)
528
                plugin_max_width = min(self._left_sidebar_max_width,
529
                                       plugin_max_width)
530
531
            # Get the view
532
            ret[p] = stats.get_plugin(p).get_stats_display(args=self.args,
533
                                                           max_width=plugin_max_width)
0 ignored issues
show
Coding Style introduced by
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...
534
535
        return ret
536
537
    def display(self, stats, cs_status=None):
538
        """Display stats on the screen.
539
540
        stats: Stats database to display
541
        cs_status:
542
            "None": standalone or server mode
543
            "Connected": Client is connected to a Glances server
544
            "SNMP": Client is connected to a SNMP server
545
            "Disconnected": Client is disconnected from the server
546
547
        Return:
548
            True if the stats have been displayed
549
            False if the help have been displayed
550
        """
551
        # Init the internal line/column for Glances Curses
552
        self.init_line_column()
553
554
        # Update the stats messages
555
        ###########################
556
557
        # Get all the plugins but quicklook and proceslist
558
        self.args.cs_status = cs_status
559
        __stat_display = self.__get_stat_display(stats, layer=cs_status)
560
561
        # Adapt number of processes to the available space
562
        max_processes_displayed = (
563
            self.term_window.getmaxyx()[0] - 11 -
564
            (0 if 'docker' not in __stat_display else
565
                self.get_stats_display_height(__stat_display["docker"])) -
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
566
            (0 if 'processcount' not in __stat_display else
567
                self.get_stats_display_height(__stat_display["processcount"])) -
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
568
            (0 if 'amps' not in __stat_display else
569
                self.get_stats_display_height(__stat_display["amps"])) -
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
570
            (0 if 'alert' not in __stat_display else
571
                self.get_stats_display_height(__stat_display["alert"])))
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 3 spaces).
Loading history...
572
573
        try:
574
            if self.args.enable_process_extended:
575
                max_processes_displayed -= 4
576
        except AttributeError:
577
            pass
578
        if max_processes_displayed < 0:
579
            max_processes_displayed = 0
580
        if (glances_processes.max_processes is None or
581
                glances_processes.max_processes != max_processes_displayed):
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation (remove 4 spaces).
Loading history...
582
            logger.debug("Set number of displayed processes to {}".format(max_processes_displayed))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (99/80).

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

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
583
            glances_processes.max_processes = max_processes_displayed
584
585
        # Get the processlist
586
        __stat_display["processlist"] = stats.get_plugin(
587
            'processlist').get_stats_display(args=self.args)
588
589
        # Display the stats on the curses interface
590
        ###########################################
591
592
        # Help screen (on top of the other stats)
593
        if self.args.help_tag:
594
            # Display the stats...
595
            self.display_plugin(
596
                stats.get_plugin('help').get_stats_display(args=self.args))
597
            # ... and exit
598
            return False
599
600
        # =====================================
601
        # Display first line (system+ip+uptime)
602
        # Optionnaly: Cloud on second line
603
        # =====================================
604
        self.__display_header(__stat_display)
605
606
        # ==============================================================
607
        # Display second line (<SUMMARY>+CPU|PERCPU+<GPU>+LOAD+MEM+SWAP)
608
        # ==============================================================
609
        self.__display_top(__stat_display, stats)
610
611
        # ==================================================================
612
        # Display left sidebar (NETWORK+PORTS+DISKIO+FS+SENSORS+Current time)
613
        # ==================================================================
614
        self.__display_left(__stat_display)
615
616
        # ====================================
617
        # Display right stats (process and co)
618
        # ====================================
619
        self.__display_right(__stat_display)
620
621
        # =====================
622
        # Others popup messages
623
        # =====================
624
625
        # Display edit filter popup
626
        # Only in standalone mode (cs_status is None)
627
        if self.edit_filter and cs_status is None:
628
            new_filter = self.display_popup(
629
                'Process filter pattern: \n\n' +
630
                'Examples:\n' +
631
                '- python\n' +
632
                '- .*python.*\n' +
633
                '- /usr/lib.*\n' +
634
                '- name:.*nautilus.*\n' +
635
                '- cmdline:.*glances.*\n' +
636
                '- username:nicolargo\n' +
637
                '- username:^root        ',
638
                popup_type='input',
639
                input_value=glances_processes.process_filter_input)
640
            glances_processes.process_filter = new_filter
641
        elif self.edit_filter and cs_status is not None:
642
            self.display_popup('Process filter only available in standalone mode')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

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

Loading history...
643
        self.edit_filter = False
644
645
        # Display kill process confirmation popup
646
        # Only in standalone mode (cs_status is None)
647
        if self.kill_process and cs_status is None:
648
            selected_process_raw = stats.get_plugin('processlist').get_raw()[
649
                self.args.cursor_position]
650
            confirm = self.display_popup(
651
                'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
652
                    selected_process_raw['name'], 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
653
                    selected_process_raw['pid']), 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
654
                    popup_type='yesno')
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
655
            if confirm.lower().startswith('y'):
656
                try:
657
                    ret_kill = glances_processes.kill(selected_process_raw['pid'])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

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

Loading history...
658
                except Exception as e:
0 ignored issues
show
Best Practice introduced by
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
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...
659
                    logger.error('Can not kill process {} ({})'.format(
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
660
                        selected_process_raw['name'], e))
661
                else:
662
                    logger.info('Kill signal has been sent to process {} (return code: {})'.format(
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (99/80).

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

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
663
                        selected_process_raw['name'], ret_kill))
664
665
        elif self.kill_process and cs_status is not None:
666
            self.display_popup(
667
                'Kill process only available in standalone mode')
668
        self.kill_process = False
669
670
671
        # Display graph generation popup
672
        if self.args.generate_graph:
673
            self.display_popup('Generate graph in {}'.format(self.args.export_graph_path))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (90/80).

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

Loading history...
674
675
        return True
676
677
    def __display_header(self, stat_display):
678
        """Display the firsts lines (header) in the Curses interface.
679
680
        system + ip + uptime
681
        (cloud)
682
        """
683
        # First line
684
        self.new_line()
685
        self.space_between_column = 0
686
        l_uptime = 1
687
        for i in ['system', 'ip', 'uptime']:
688
            if i in stat_display:
689
                l_uptime += self.get_stats_display_width(stat_display[i])
690
        self.display_plugin(
691
            stat_display["system"],
692
            display_optional=(self.term_window.getmaxyx()[1] >= l_uptime))
693
        self.space_between_column = 3
694
        if 'ip' in stat_display:
695
            self.new_column()
696
            self.display_plugin(stat_display["ip"])
697
        self.new_column()
698
        self.display_plugin(
699
            stat_display["uptime"],
700
            add_space=-(self.get_stats_display_width(stat_display["cloud"]) != 0))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

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

Loading history...
701
        # Second line (optional)
702
        self.init_column()
703
        self.new_line()
704
        self.display_plugin(stat_display["cloud"])
705
706
    def __display_top(self, stat_display, stats):
707
        """Display the second line in the Curses interface.
708
709
        <QUICKLOOK> + CPU|PERCPU + <GPU> + MEM + SWAP + LOAD
710
        """
711
        self.init_column()
712
        self.new_line()
713
714
        # Init quicklook
715
        stat_display['quicklook'] = {'msgdict': []}
716
717
        # Dict for plugins width
718
        plugin_widths = {}
719
        for p in self._top:
0 ignored issues
show
Coding Style Naming introduced by
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...
720
            plugin_widths[p] = self.get_stats_display_width(stat_display.get(p, 0)) if hasattr(self.args, 'disable_' + p) else 0
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (128/80).

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

Loading history...
721
722
        # Width of all plugins
723
        stats_width = sum(itervalues(plugin_widths))
724
725
        # Number of plugin but quicklook
726
        stats_number = sum([int(stat_display[p]['msgdict'] != []) for p in self._top if not getattr(self.args, 'disable_' + p)])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (128/80).

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

Loading history...
727
728
        if not self.args.disable_quicklook:
729
            # Quick look is in the place !
730
            if self.args.full_quicklook:
731
                quicklook_width = self.term_window.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (127/80).

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

Loading history...
732
            else:
733
                quicklook_width = min(self.term_window.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column),
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (132/80).

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

Loading history...
734
                                      self._quicklook_max_width - 5)
735
            try:
736
                stat_display["quicklook"] = stats.get_plugin(
737
                    'quicklook').get_stats_display(max_width=quicklook_width, args=self.args)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (93/80).

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

Loading history...
738
            except AttributeError as e:
0 ignored issues
show
Coding Style Naming introduced by
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...
739
                logger.debug("Quicklook plugin not available (%s)" % e)
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
740
            else:
741
                plugin_widths['quicklook'] = self.get_stats_display_width(stat_display["quicklook"])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (100/80).

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

Loading history...
742
                stats_width = sum(itervalues(plugin_widths)) + 1
743
            self.space_between_column = 1
744
            self.display_plugin(stat_display["quicklook"])
745
            self.new_column()
746
747
        # Compute spaces between plugins
748
        # Note: Only one space between Quicklook and others
749
        plugin_display_optional = {}
750
        for p in self._top:
0 ignored issues
show
Coding Style Naming introduced by
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...
751
            plugin_display_optional[p] = True
752
        if stats_number > 1:
753
            self.space_between_column = max(1, int((self.term_window.getmaxyx()[1] - stats_width) / (stats_number - 1)))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/80).

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

Loading history...
introduced by
division w/o __future__ statement
Loading history...
754
            for p in ['mem', 'cpu']:
0 ignored issues
show
Coding Style Naming introduced by
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...
755
                # No space ? Remove optional stats
756
                if self.space_between_column < 3:
757
                    plugin_display_optional[p] = False
758
                    plugin_widths[p] = self.get_stats_display_width(stat_display[p], without_option=True) if hasattr(self.args, 'disable_' + p) else 0
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (150/80).

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

Loading history...
759
                    stats_width = sum(itervalues(plugin_widths)) + 1
760
                    self.space_between_column = max(1, int((self.term_window.getmaxyx()[1] - stats_width) / (stats_number - 1)))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (128/80).

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

Loading history...
introduced by
division w/o __future__ statement
Loading history...
761
        else:
762
            self.space_between_column = 0
763
764
        # Display CPU, MEM, SWAP and LOAD
765
        for p in self._top:
0 ignored issues
show
Coding Style Naming introduced by
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...
766
            if p == 'quicklook':
767
                continue
768
            if p in stat_display:
769
                self.display_plugin(stat_display[p],
770
                                    display_optional=plugin_display_optional[p])
771
            if p != 'load':
772
                # Skip last column
773
                self.new_column()
774
775
        # Space between column
776
        self.space_between_column = 3
777
778
        # Backup line position
779
        self.saved_line = self.next_line
0 ignored issues
show
Coding Style introduced by
The attribute saved_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...
780
781
    def __display_left(self, stat_display):
782
        """Display the left sidebar in the Curses interface."""
783
        self.init_column()
784
785
        if self.args.disable_left_sidebar:
786
            return
787
788
        for p in self._left_sidebar:
0 ignored issues
show
Coding Style Naming introduced by
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...
789
            if ((hasattr(self.args, 'enable_' + p) or
790
                 hasattr(self.args, 'disable_' + p)) and p in stat_display):
791
                self.new_line()
792
                self.display_plugin(stat_display[p])
793
794
    def __display_right(self, stat_display):
795
        """Display the right sidebar in the Curses interface.
796
797
        docker + processcount + amps + processlist + alert
798
        """
799
        # Do not display anything if space is not available...
800
        if self.term_window.getmaxyx()[1] < self._left_sidebar_min_width:
801
            return
802
803
        # Restore line position
804
        self.next_line = self.saved_line
0 ignored issues
show
Coding Style introduced by
The attribute next_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...
805
806
        # Display right sidebar
807
        self.new_column()
808
        for p in self._right_sidebar:
0 ignored issues
show
Coding Style Naming introduced by
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...
809
            if ((hasattr(self.args, 'enable_' + p) or
810
                 hasattr(self.args, 'disable_' + p)) and p in stat_display):
811
                if p not in p:
812
                    # Catch for issue #1470
813
                    continue
814
                self.new_line()
815
                if p == 'processlist':
816
                    self.display_plugin(stat_display['processlist'],
817
                                        display_optional=(self.term_window.getmaxyx()[1] > 102),
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (96/80).

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

Loading history...
818
                                        display_additional=(not MACOS),
819
                                        max_y=(self.term_window.getmaxyx()[0] - self.get_stats_display_height(stat_display['alert']) - 2))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (138/80).

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

Loading history...
820
                else:
821
                    self.display_plugin(stat_display[p])
822
823
    def display_popup(self, message,
0 ignored issues
show
best-practice introduced by
Too many arguments (8/5)
Loading history...
Comprehensibility introduced by
This function exceeds the maximum number of variables (18/15).
Loading history...
824
                      size_x=None, size_y=None,
825
                      duration=3,
826
                      popup_type='info',
827
                      input_size=30,
828
                      input_value=None):
829
        """
830
        Display a centered popup.
831
832
        popup_type='info'
833
         Just an infotmation popup, no user interaction
834
         Display a centered popup with the given message during duration seconds
835
         If size_x and size_y: set the popup size
836
         else set it automatically
837
         Return True if the popup could be displayed
838
839
        popup_type='input'
840
         Display a centered popup with the given message and a input field
841
         If size_x and size_y: set the popup size
842
         else set it automatically
843
         Return the input string or None if the field is empty
844
845
        popup_type='yesno'
846
         Display a centered popup with the given message
847
         If size_x and size_y: set the popup size
848
         else set it automatically
849
         Return True (yes) or False (no)
850
        """
851
        # Center the popup
852
        sentence_list = message.split('\n')
853
        if size_x is None:
854
            size_x = len(max(sentence_list, key=len)) + 4
855
            # Add space for the input field
856
            if popup_type == 'input':
857
                size_x += input_size
858
        if size_y is None:
859
            size_y = len(sentence_list) + 4
860
        screen_x = self.term_window.getmaxyx()[1]
861
        screen_y = self.term_window.getmaxyx()[0]
862
        if size_x > screen_x or size_y > screen_y:
863
            # No size to display the popup => abord
864
            return False
865
        pos_x = int((screen_x - size_x) / 2)
0 ignored issues
show
introduced by
division w/o __future__ statement
Loading history...
866
        pos_y = int((screen_y - size_y) / 2)
0 ignored issues
show
introduced by
division w/o __future__ statement
Loading history...
867
868
        # Create the popup
869
        popup = curses.newwin(size_y, size_x, pos_y, pos_x)
0 ignored issues
show
Bug introduced by
The Module curses does not seem to have a member named newwin.

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...
870
871
        # Fill the popup
872
        popup.border()
873
874
        # Add the message
875
        for y, m in enumerate(sentence_list):
0 ignored issues
show
Coding Style Naming introduced by
The name y 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...
Coding Style Naming introduced by
The name m 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...
876
            popup.addnstr(2 + y, 2, m, len(m))
877
878
        if popup_type == 'info':
879
            # Display the popup
880
            popup.refresh()
881
            self.wait(duration * 1000)
882
            return True
883
        elif popup_type == 'input':
884
            # Create a subwindow for the text field
885
            subpop = popup.derwin(1, input_size, 2, 2 + len(m))
0 ignored issues
show
Bug introduced by
The loop variable m might not be defined here.
Loading history...
introduced by
The variable m does not seem to be defined in case the for loop on line 875 is not entered. Are you sure this can never be the case?
Loading history...
886
            subpop.attron(self.colors_list['FILTER'])
887
            # Init the field with the current value
888
            if input_value is not None:
889
                subpop.addnstr(0, 0, input_value, len(input_value))
890
            # Display the popup
891
            popup.refresh()
892
            subpop.refresh()
893
            # Create the textbox inside the subwindows
894
            self.set_cursor(2)
895
            self.term_window.keypad(1)
896
            textbox = GlancesTextbox(subpop, insert_mode=True)
897
            textbox.edit()
898
            self.set_cursor(0)
899
            # self.term_window.keypad(0)
900
            if textbox.gather() != '':
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
901
                logger.debug(
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
902
                    "User enters the following string: %s" % textbox.gather())
903
                return textbox.gather()[:-1]
904
            else:
905
                logger.debug("User centers an empty string")
906
                return None
907
        elif popup_type == 'yesno':
908
            # # Create a subwindow for the text field
909
            subpop = popup.derwin(1, 2, len(sentence_list) + 1, len(m) + 2)
0 ignored issues
show
Bug introduced by
The loop variable m might not be defined here.
Loading history...
910
            subpop.attron(self.colors_list['FILTER'])
911
            # Init the field with the current value
912
            subpop.addnstr(0, 0, '', 0)
913
            # Display the popup
914
            popup.refresh()
915
            subpop.refresh()
916
            # Create the textbox inside the subwindows
917
            self.set_cursor(2)
918
            self.term_window.keypad(1)
919
            textbox = GlancesTextboxYesNo(subpop, insert_mode=False)
920
            textbox.edit()
921
            self.set_cursor(0)
922
            # self.term_window.keypad(0)
923
            return textbox.gather()
924
925
    def display_plugin(self, plugin_stats,
0 ignored issues
show
best-practice introduced by
Too many arguments (6/5)
Loading history...
926
                       display_optional=True,
927
                       display_additional=True,
928
                       max_y=65535,
929
                       add_space=0):
930
        """Display the plugin_stats on the screen.
931
932
        If display_optional=True display the optional stats
933
        If display_additional=True display additionnal stats
934
        max_y: do not display line > max_y
935
        add_space: add x space (line) after the plugin
936
        """
937
        # Exit if:
938
        # - the plugin_stats message is empty
939
        # - the display tag = False
940
        if plugin_stats is None or not plugin_stats['msgdict'] or not plugin_stats['display']:
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (94/80).

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

Loading history...
941
            # Exit
942
            return 0
943
944
        # Get the screen size
945
        screen_x = self.term_window.getmaxyx()[1]
946
        screen_y = self.term_window.getmaxyx()[0]
947
948
        # Set the upper/left position of the message
949
        if plugin_stats['align'] == 'right':
950
            # Right align (last column)
951
            display_x = screen_x - self.get_stats_display_width(plugin_stats)
952
        else:
953
            display_x = self.column
954
        if plugin_stats['align'] == 'bottom':
955
            # Bottom (last line)
956
            display_y = screen_y - self.get_stats_display_height(plugin_stats)
957
        else:
958
            display_y = self.line
959
960
        # Display
961
        x = display_x
0 ignored issues
show
Coding Style Naming introduced by
The name x 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...
962
        x_max = x
963
        y = display_y
0 ignored issues
show
Coding Style Naming introduced by
The name y 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...
964
        for m in plugin_stats['msgdict']:
0 ignored issues
show
Coding Style Naming introduced by
The name m 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...
965
            # New line
966
            try:
967
                if m['msg'].startswith('\n'):
968
                    # Go to the next line
969
                    y += 1
0 ignored issues
show
Coding Style Naming introduced by
The name y 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...
970
                    # Return to the first column
971
                    x = display_x
0 ignored issues
show
Coding Style Naming introduced by
The name x 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...
972
                    continue
973
            except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
974
                # Avoid exception (see issue #1692)
975
                pass
976
            # Do not display outside the screen
977
            if x < 0:
978
                continue
979
            if not m['splittable'] and (x + len(m['msg']) > screen_x):
980
                continue
981
            if y < 0 or (y + 1 > screen_y) or (y > max_y):
982
                break
983
            # If display_optional = False do not display optional stats
984
            if not display_optional and m['optional']:
985
                continue
986
            # If display_additional = False do not display additional stats
987
            if not display_additional and m['additional']:
988
                continue
989
            # Is it possible to display the stat with the current screen size
990
            # !!! Crach if not try/except... Why ???
991
            try:
992
                self.term_window.addnstr(y, x,
993
                                         m['msg'],
994
                                         # Do not disply outside the screen
995
                                         screen_x - x,
996
                                         self.colors_list[m['decoration']])
997
            except Exception:
0 ignored issues
show
Best Practice introduced by
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...
998
                pass
999
            else:
1000
                # New column
1001
                # Python 2: we need to decode to get real screen size because
1002
                # UTF-8 special tree chars occupy several bytes.
1003
                # Python 3: strings are strings and bytes are bytes, all is
1004
                # good.
1005
                try:
1006
                    x += len(u(m['msg']))
0 ignored issues
show
Coding Style Naming introduced by
The name x 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...
1007
                except UnicodeDecodeError:
1008
                    # Quick and dirty hack for issue #745
1009
                    pass
1010
                if x > x_max:
1011
                    x_max = x
1012
1013
        # Compute the next Glances column/line position
1014
        self.next_column = max(
0 ignored issues
show
Coding Style introduced by
The attribute next_column 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...
1015
            self.next_column, x_max + self.space_between_column)
1016
        self.next_line = max(self.next_line, y + self.space_between_line)
0 ignored issues
show
Coding Style introduced by
The attribute next_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...
1017
1018
        # Have empty lines after the plugins
1019
        self.next_line += add_space
1020
1021
    def erase(self):
1022
        """Erase the content of the screen."""
1023
        self.term_window.erase()
1024
1025
    def flush(self, stats, cs_status=None):
1026
        """Clear and update the screen.
1027
1028
        stats: Stats database to display
1029
        cs_status:
1030
            "None": standalone or server mode
1031
            "Connected": Client is connected to the server
1032
            "Disconnected": Client is disconnected from the server
1033
        """
1034
        self.erase()
1035
        self.display(stats, cs_status=cs_status)
1036
1037
    def update(self,
1038
               stats,
1039
               duration=3,
1040
               cs_status=None,
1041
               return_to_browser=False):
1042
        """Update the screen.
1043
1044
        INPUT
1045
        stats: Stats database to display
1046
        duration: duration of the loop
1047
        cs_status:
1048
            "None": standalone or server mode
1049
            "Connected": Client is connected to the server
1050
            "Disconnected": Client is disconnected from the server
1051
        return_to_browser:
1052
            True: Do not exist, return to the browser list
1053
            False: Exit and return to the shell
1054
1055
        OUTPUT
1056
        True: Exit key has been pressed
1057
        False: Others cases...
1058
        """
1059
        # Flush display
1060
        self.flush(stats, cs_status=cs_status)
1061
1062
        # If the duration is < 0 (update + export time > refresh_time)
1063
        # Then display the interface and log a message
1064
        if duration <= 0:
1065
            logger.warning('Update and export time higher than refresh_time.')
1066
            duration = 0.1
1067
1068
        # Wait duration (in s) time
1069
        exitkey = False
1070
        countdown = Timer(duration)
1071
        # Set the default timeout (in ms) for the getch method
1072
        self.term_window.timeout(int(duration * 1000))
1073
        while not countdown.finished() and not exitkey:
1074
            # Getkey
1075
            pressedkey = self.__catch_key(return_to_browser=return_to_browser)
1076
            # Is it an exit key ?
1077
            exitkey = (pressedkey == ord('\x1b') or pressedkey == ord('q'))
1078
            if pressedkey == curses.KEY_F5:
0 ignored issues
show
Bug introduced by
Module 'curses' has no 'KEY_F5' member; maybe 'KEY_F0'?

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...
1079
                # were asked to refresh
1080
                return exitkey
1081
            if not exitkey and pressedkey > -1:
1082
                # Redraw display
1083
                self.flush(stats, cs_status=cs_status)
1084
                # Overwrite the timeout with the countdown
1085
                self.term_window.timeout(int(countdown.get() * 1000))
1086
1087
        return exitkey
1088
1089
    def wait(self, delay=100):
0 ignored issues
show
Unused Code introduced by
The argument delay seems to be unused.
Loading history...
Coding Style introduced by
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...
1090
        """Wait delay in ms"""
1091
        curses.napms(100)
0 ignored issues
show
Bug introduced by
The Module curses does not seem to have a member named napms.

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...
1092
1093
    def get_stats_display_width(self, curse_msg, without_option=False):
0 ignored issues
show
Coding Style introduced by
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...
1094
        """Return the width of the formatted curses message."""
1095
        try:
1096
            if without_option:
1097
                # Size without options
1098
                c = len(max(''.join([(u(u(nativestr(i['msg'])).encode('ascii', 'replace')) if not i['optional'] else "")
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (120/80).

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

Loading history...
Coding Style Naming introduced by
The name c 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...
1099
                                     for i in curse_msg['msgdict']]).split('\n'), key=len))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

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

Loading history...
1100
            else:
1101
                # Size with all options
1102
                c = len(max(''.join([u(u(nativestr(i['msg'])).encode('ascii', 'replace'))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (89/80).

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

Loading history...
Coding Style Naming introduced by
The name c 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...
1103
                                     for i in curse_msg['msgdict']]).split('\n'), key=len))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

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

Loading history...
1104
        except Exception as e:
0 ignored issues
show
Best Practice introduced by
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
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...
1105
            logger.debug('ERROR: Can not compute plugin width ({})'.format(e))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
1106
            return 0
1107
        else:
1108
            return c
1109
1110
    def get_stats_display_height(self, curse_msg):
0 ignored issues
show
Coding Style introduced by
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...
1111
        r"""Return the height of the formatted curses message.
1112
1113
        The height is defined by the number of '\n' (new line).
1114
        """
1115
        try:
1116
            c = [i['msg'] for i in curse_msg['msgdict']].count('\n')
0 ignored issues
show
Coding Style Naming introduced by
The name c 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...
1117
        except Exception as e:
0 ignored issues
show
Best Practice introduced by
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
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...
1118
            logger.debug('ERROR: Can not compute plugin height ({})'.format(e))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
1119
            return 0
1120
        else:
1121
            return c + 1
1122
1123
1124
class GlancesCursesStandalone(_GlancesCurses):
1125
1126
    """Class for the Glances curse standalone."""
1127
1128
    pass
1129
1130
1131
class GlancesCursesClient(_GlancesCurses):
1132
1133
    """Class for the Glances curse client."""
1134
1135
    pass
1136
1137
1138
class GlancesTextbox(Textbox, object):
0 ignored issues
show
Coding Style introduced by
This class 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...
1139
1140
    def __init__(self, *args, **kwargs):
0 ignored issues
show
introduced by
Useless super delegation in method '__init__'
Loading history...
1141
        super(GlancesTextbox, self).__init__(*args, **kwargs)
1142
1143
    def do_command(self, ch):
1144
        if ch == 10:  # Enter
1145
            return 0
1146
        if ch == 127:  # Back
1147
            return 8
1148
        return super(GlancesTextbox, self).do_command(ch)
1149
1150
1151
class GlancesTextboxYesNo(Textbox, object):
0 ignored issues
show
Coding Style introduced by
This class 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...
1152
1153
    def __init__(self, *args, **kwargs):
0 ignored issues
show
introduced by
Useless super delegation in method '__init__'
Loading history...
1154
        super(GlancesTextboxYesNo, self).__init__(*args, **kwargs)
1155
1156
    def do_command(self, ch):
0 ignored issues
show
introduced by
Useless super delegation in method 'do_command'
Loading history...
1157
        return super(GlancesTextboxYesNo, self).do_command(ch)
1158