Test Failed
Push — develop ( d7cf39...faa4bd )
by Nicolas
04:34 queued 10s
created

glances/folder_list.py (27 issues)

1
# -*- coding: utf-8 -*-
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
"""Manage the folder list."""
21
from __future__ import unicode_literals
22
23
import os
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
24
25
from glances.timer import Timer
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
26
from glances.compat import range, nativestr
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in range.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
import missing from __future__ import absolute_import
Loading history...
27
from glances.logger import logger
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
28
29
# Use the built-in version of scandir/walk if possible, otherwise
30
# use the scandir module version
31
scandir_tag = True
0 ignored issues
show
Coding Style Naming introduced by
The name scandir_tag does not conform to the constant naming conventions ((([A-Z_][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...
32
try:
33
    # For Python 3.5 or higher
34
    from os import scandir
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
35
except ImportError:
36
    # For others...
37
    try:
38
        from scandir import scandir
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
39
    except ImportError:
40
        scandir_tag = False
0 ignored issues
show
Coding Style Naming introduced by
The name scandir_tag does not conform to the constant naming conventions ((([A-Z_][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...
41
42
43
class FolderList(object):
44
45
    """This class describes the optional monitored folder list.
46
47
    The folder list is a list of 'important' folder to monitor.
48
49
    The list (Python list) is composed of items (Python dict).
50
    An item is defined (dict keys):
51
    * path: Path to the folder
52
    * careful: optional careful threshold (in MB)
53
    * warning: optional warning threshold (in MB)
54
    * critical: optional critical threshold (in MB)
55
    """
56
57
    # Maximum number of items in the list
58
    __folder_list_max_size = 10
59
    # The folder list
60
    __folder_list = []
61
    # Default refresh time is 30 seconds for this plugins
62
    __default_refresh = 30
63
64
    def __init__(self, config):
65
        """Init the folder list from the configuration file, if it exists."""
66
        self.config = config
67
68
        # A list of Timer
69
        # One timer per folder
70
        # default timer is __default_refresh, can be overwrite by folder_1_refresh=600
0 ignored issues
show
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...
71
        self.timer_folders = []
72
        self.first_grab = True
73
74
        if self.config is not None and self.config.has_section('folders'):
75
            if scandir_tag:
76
                # Process monitoring list
77
                logger.debug("Folder list configuration detected")
78
                self.__set_folder_list('folders')
79
            else:
80
                logger.error('Scandir not found. Please use Python 3.5+ or install the scandir lib')
0 ignored issues
show
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...
81
        else:
82
            self.__folder_list = []
83
84
    def __set_folder_list(self, section):
85
        """Init the monitored folder list.
86
87
        The list is defined in the Glances configuration file.
88
        """
89
        for l in range(1, self.__folder_list_max_size + 1):
0 ignored issues
show
Coding Style Naming introduced by
The name l 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...
90
            value = {}
91
            key = 'folder_' + str(l) + '_'
92
93
            # Path is mandatory
94
            value['indice'] = str(l)
95
            value['path'] = self.config.get_value(section, key + 'path')
96
            if value['path'] is None:
97
                continue
98
            else:
99
                value['path'] = nativestr(value['path'])
100
101
            # Optional conf keys
102
            # Refresh time
103
            value['refresh'] = int(self.config.get_value(section,
104
                                                         key + 'refresh',
105
                                                         default=self.__default_refresh))
0 ignored issues
show
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...
106
            self.timer_folders.append(Timer(value['refresh']))
107
            # Thesholds
108
            for i in ['careful', 'warning', 'critical']:
109
                # Read threshold
110
                value[i] = self.config.get_value(section, key + i)
111
                if value[i] is not None:
112
                    logger.debug("{} threshold for folder {} is {}".format(i, value["path"], value[i]))
0 ignored issues
show
This line is too long as per the coding-style (103/80).

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

Loading history...
Use formatting in logging functions and pass the parameters as arguments
Loading history...
113
                # Read action
114
                action = self.config.get_value(section, key + i + '_action')
115
                if action is not None:
116
                    value[i + '_action'] = action
117
                    logger.debug("{} action for folder {} is {}".format(i, value["path"], value[i + '_action']))
0 ignored issues
show
This line is too long as per the coding-style (112/80).

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

Loading history...
Use formatting in logging functions and pass the parameters as arguments
Loading history...
118
119
            # Add the item to the list
120
            self.__folder_list.append(value)
121
122
    def __str__(self):
123
        return str(self.__folder_list)
124
125
    def __repr__(self):
126
        return self.__folder_list
127
128
    def __getitem__(self, item):
129
        return self.__folder_list[item]
130
131
    def __len__(self):
132
        return len(self.__folder_list)
133
134
    def __get__(self, item, key):
135
        """Meta function to return key value of item.
136
137
        Return None if not defined or item > len(list)
138
        """
139
        if item < len(self.__folder_list):
140
            try:
141
                return self.__folder_list[item][key]
142
            except Exception:
0 ignored issues
show
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...
143
                return None
144
        else:
145
            return None
146
147
    def __folder_size(self, path):
148
        """Return the size of the directory given by path
149
150
        path: <string>"""
151
152
        ret = 0
153
        for f in scandir(path):
0 ignored issues
show
Coding Style Naming introduced by
The name f 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...
154
            if f.is_dir() and (f.name != '.' or f.name != '..'):
155
                ret += self.__folder_size(os.path.join(path, f.name))
156
            else:
157
                try:
158
                    ret += f.stat().st_size
159
                except OSError:
160
                    pass
161
162
        return ret
163
164
    def update(self):
165
        """Update the command result attributed."""
166
        # Only continue if monitor list is not empty
167
        if len(self.__folder_list) == 0:
0 ignored issues
show
Do not use len(SEQUENCE) as condition value
Loading history...
168
            return self.__folder_list
169
170
        # Iter upon the folder list
171
        for i in range(len(self.get())):
172
            # Update folder size
173
            if not self.first_grab and not self.timer_folders[i].finished():
174
                continue
175
            # Get folder size
176
            try:
177
                self.__folder_list[i]['size'] = self.__folder_size(self.path(i))
178
            except OSError 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...
179
                logger.debug('Cannot get folder size ({}). Error: {}'.format(self.path(i), e))
0 ignored issues
show
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...
Use formatting in logging functions and pass the parameters as arguments
Loading history...
180
                if e.errno == 13:
181
                    # Permission denied
182
                    self.__folder_list[i]['size'] = '!'
183
                else:
184
                    self.__folder_list[i]['size'] = '?'
185
            # Reset the timer
186
            self.timer_folders[i].reset()
187
188
        # It is no more the first time...
189
        self.first_grab = False
190
191
        return self.__folder_list
192
193
    def get(self):
194
        """Return the monitored list (list of dict)."""
195
        return self.__folder_list
196
197
    def set(self, newlist):
198
        """Set the monitored list (list of dict)."""
199
        self.__folder_list = newlist
200
201
    def getAll(self):
0 ignored issues
show
Coding Style Naming introduced by
The name getAll does not conform to the method 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...
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...
202
        # Deprecated: use get()
203
        return self.get()
204
205
    def setAll(self, newlist):
0 ignored issues
show
Coding Style Naming introduced by
The name setAll does not conform to the method 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...
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...
206
        # Deprecated: use set()
207
        self.set(newlist)
208
209
    def path(self, item):
210
        """Return the path of the item number (item)."""
211
        return self.__get__(item, "path")
212
213
    def careful(self, item):
214
        """Return the careful threshold of the item number (item)."""
215
        return self.__get__(item, "careful")
216
217
    def warning(self, item):
218
        """Return the warning threshold of the item number (item)."""
219
        return self.__get__(item, "warning")
220
221
    def critical(self, item):
222
        """Return the critical threshold of the item number (item)."""
223
        return self.__get__(item, "critical")
224