Completed
Push — master ( bcff18...adb900 )
by Nicolas
01:15
created

glances.Config.read()   F

Complexity

Conditions 14

Size

Total Lines 108

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 14
dl 0
loc 108
rs 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

Complexity

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

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

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 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 configuration file."""
21
22
import os
23
import sys
24
from io import open
25
26
from glances.compat import ConfigParser, NoOptionError
27
from glances.globals import appname, BSD, LINUX, OSX, WINDOWS, sys_prefix
28
from glances.logger import logger
29
30
31
class Config(object):
32
33
    """This class is used to access/read config file, if it exists.
34
35
    :param config_dir: the path to search for config file
36
    :type config_dir: str or None
37
    """
38
39
    def __init__(self, config_dir=None):
40
        self.config_dir = config_dir
41
        self.config_filename = 'glances.conf'
42
        self._loaded_config_file = None
43
44
        self.parser = ConfigParser()
45
        self.read()
46
47
    def config_file_paths(self):
48
        r"""Get a list of config file paths.
49
50
        The list is built taking into account of the OS, priority and location.
51
52
        * custom path: /path/to/glances
53
        * Linux: ~/.config/glances, /etc/glances
54
        * BSD: ~/.config/glances, /usr/local/etc/glances
55
        * OS X: ~/Library/Application Support/glances, /usr/local/etc/glances
56
        * Windows: %APPDATA%\glances
57
58
        The config file will be searched in the following order of priority:
59
            * /path/to/file (via -C flag)
60
            * user's home directory (per-user settings)
61
            * system-wide directory (system-wide settings)
62
        """
63
        paths = []
64
65
        if self.config_dir:
66
            paths.append(self.config_dir)
67
68
        if LINUX or BSD:
69
            paths.append(
70
                os.path.join(os.environ.get('XDG_CONFIG_HOME') or
71
                             os.path.expanduser('~/.config'),
72
                             appname, self.config_filename))
73
            if BSD:
74
                paths.append(
75
                    os.path.join(sys.prefix, 'etc', appname, self.config_filename))
76
            else:
77
                paths.append(
78
                    os.path.join('/etc', appname, self.config_filename))
79
        elif OSX:
80
            paths.append(
81
                os.path.join(os.path.expanduser('~/Library/Application Support/'),
82
                             appname, self.config_filename))
83
            paths.append(
84
                os.path.join(sys_prefix, 'etc', appname, self.config_filename))
85
        elif WINDOWS:
86
            paths.append(
87
                os.path.join(os.environ.get('APPDATA'), appname, self.config_filename))
88
89
        return paths
90
91
    def read(self):
92
        """Read the config file, if it exists. Using defaults otherwise."""
93
        for config_file in self.config_file_paths():
94
            if os.path.exists(config_file):
95
                try:
96
                    with open(config_file, encoding='utf-8') as f:
97
                        self.parser.read_file(f)
98
                        self.parser.read(f)
99
                    logger.info("Read configuration file '{0}'".format(config_file))
100
                except UnicodeDecodeError as err:
101
                    logger.error("Cannot decode configuration file '{0}': {1}".format(config_file, err))
102
                    sys.exit(1)
103
                # Save the loaded configuration file path (issue #374)
104
                self._loaded_config_file = config_file
105
                break
106
107
        # Quicklook
108
        if not self.parser.has_section('quicklook'):
109
            self.parser.add_section('quicklook')
110
            self.parser.set('quicklook', 'cpu_careful', '50')
111
            self.parser.set('quicklook', 'cpu_warning', '70')
112
            self.parser.set('quicklook', 'cpu_critical', '90')
113
            self.parser.set('quicklook', 'mem_careful', '50')
114
            self.parser.set('quicklook', 'mem_warning', '70')
115
            self.parser.set('quicklook', 'mem_critical', '90')
116
            self.parser.set('quicklook', 'swap_careful', '50')
117
            self.parser.set('quicklook', 'swap_warning', '70')
118
            self.parser.set('quicklook', 'swap_critical', '90')
119
120
        # CPU
121
        if not self.parser.has_section('cpu'):
122
            self.parser.add_section('cpu')
123
            self.parser.set('cpu', 'user_careful', '50')
124
            self.parser.set('cpu', 'user_warning', '70')
125
            self.parser.set('cpu', 'user_critical', '90')
126
            self.parser.set('cpu', 'iowait_careful', '50')
127
            self.parser.set('cpu', 'iowait_warning', '70')
128
            self.parser.set('cpu', 'iowait_critical', '90')
129
            self.parser.set('cpu', 'system_careful', '50')
130
            self.parser.set('cpu', 'system_warning', '70')
131
            self.parser.set('cpu', 'system_critical', '90')
132
            self.parser.set('cpu', 'steal_careful', '50')
133
            self.parser.set('cpu', 'steal_warning', '70')
134
            self.parser.set('cpu', 'steal_critical', '90')
135
136
        # Per-CPU
137
        if not self.parser.has_section('percpu'):
138
            self.parser.add_section('percpu')
139
            self.parser.set('percpu', 'user_careful', '50')
140
            self.parser.set('percpu', 'user_warning', '70')
141
            self.parser.set('percpu', 'user_critical', '90')
142
            self.parser.set('percpu', 'iowait_careful', '50')
143
            self.parser.set('percpu', 'iowait_warning', '70')
144
            self.parser.set('percpu', 'iowait_critical', '90')
145
            self.parser.set('percpu', 'system_careful', '50')
146
            self.parser.set('percpu', 'system_warning', '70')
147
            self.parser.set('percpu', 'system_critical', '90')
148
149
        # Load
150
        if not self.parser.has_section('load'):
151
            self.parser.add_section('load')
152
            self.parser.set('load', 'careful', '0.7')
153
            self.parser.set('load', 'warning', '1.0')
154
            self.parser.set('load', 'critical', '5.0')
155
156
        # Mem
157
        if not self.parser.has_section('mem'):
158
            self.parser.add_section('mem')
159
            self.parser.set('mem', 'careful', '50')
160
            self.parser.set('mem', 'warning', '70')
161
            self.parser.set('mem', 'critical', '90')
162
163
        # Swap
164
        if not self.parser.has_section('memswap'):
165
            self.parser.add_section('memswap')
166
            self.parser.set('memswap', 'careful', '50')
167
            self.parser.set('memswap', 'warning', '70')
168
            self.parser.set('memswap', 'critical', '90')
169
170
        # FS
171
        if not self.parser.has_section('fs'):
172
            self.parser.add_section('fs')
173
            self.parser.set('fs', 'careful', '50')
174
            self.parser.set('fs', 'warning', '70')
175
            self.parser.set('fs', 'critical', '90')
176
177
        # Sensors
178
        if not self.parser.has_section('sensors'):
179
            self.parser.add_section('sensors')
180
            self.parser.set('sensors', 'temperature_core_careful', '60')
181
            self.parser.set('sensors', 'temperature_core_warning', '70')
182
            self.parser.set('sensors', 'temperature_core_critical', '80')
183
            self.parser.set('sensors', 'temperature_hdd_careful', '45')
184
            self.parser.set('sensors', 'temperature_hdd_warning', '52')
185
            self.parser.set('sensors', 'temperature_hdd_critical', '60')
186
            self.parser.set('sensors', 'battery_careful', '80')
187
            self.parser.set('sensors', 'battery_warning', '90')
188
            self.parser.set('sensors', 'battery_critical', '95')
189
190
        # Process list
191
        if not self.parser.has_section('processlist'):
192
            self.parser.add_section('processlist')
193
            self.parser.set('processlist', 'cpu_careful', '50')
194
            self.parser.set('processlist', 'cpu_warning', '70')
195
            self.parser.set('processlist', 'cpu_critical', '90')
196
            self.parser.set('processlist', 'mem_careful', '50')
197
            self.parser.set('processlist', 'mem_warning', '70')
198
            self.parser.set('processlist', 'mem_critical', '90')
199
200
    @property
201
    def loaded_config_file(self):
202
        """Return the loaded configuration file."""
203
        return self._loaded_config_file
204
205
    def items(self, section):
206
        """Return the items list of a section."""
207
        return self.parser.items(section)
208
209
    def has_section(self, section):
210
        """Return info about the existence of a section."""
211
        return self.parser.has_section(section)
212
213
    def get_value(self, section, option, default=None):
214
        """Get the value of an option, if it exists."""
215
        try:
216
            return self.parser.get(section, option)
217
        except NoOptionError:
218
            return default
219
220
    def get_float_value(self, section, option, default=0.0):
221
        """Get the float value of an option, if it exists."""
222
        try:
223
            return self.parser.getfloat(section, option)
224
        except NoOptionError:
225
            return float(default)
226