Test Failed
Push — develop ( 0abc39...ef45c6 )
by Nicolas
02:52
created

glances.api.GlancesAPI.bar()   A

Complexity

Conditions 1

Size

Total Lines 20
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 7
dl 0
loc 20
rs 10
c 0
b 0
f 0
1
#
2
# Glances - An eye on your system
3
#
4
# SPDX-FileCopyrightText: 2025 Nicolas Hennion <[email protected]>
5
#
6
# SPDX-License-Identifier: LGPL-3.0-only
7
#
8
9
from glances import __version__ as glances_version
10
from glances.globals import auto_unit, weak_lru_cache
11
from glances.main import GlancesMain
12
from glances.outputs.glances_bars import Bar
13
from glances.processes import sort_stats
14
from glances.stats import GlancesStats
15
16
plugin_dependencies_tree = {
17
    'processlist': ['processcount'],
18
}
19
20
21
class GlancesAPI:
22
    ttl = 2.0  # Default cache TTL in seconds
23
24
    def __init__(self, config=None, args=None, args_begin_at=1):
25
        self.__version__ = glances_version.split('.')[0]  # Get the major version
26
27
        core = GlancesMain(args_begin_at)
28
        self.args = args if args is not None else core.get_args()
29
        self.config = config if config is not None else core.get_config()
30
        self._stats = GlancesStats(config=self.config, args=self.args)
31
32
        # Set the cache TTL for the API
33
        self.ttl = self.args.time if self.args.time is not None else self.ttl
34
35
        # Init the stats of all plugins in order to ensure that rate are computed
36
        self._stats.update()
37
38
    @weak_lru_cache(maxsize=1, ttl=ttl)
39
    def __getattr__(self, item):
40
        """Fallback to the stats object for any missing attributes."""
41
        if item in self._stats.getPluginsList():
42
            if item in plugin_dependencies_tree:
43
                # Ensure dependencies are updated before accessing the plugin
44
                for dependency in plugin_dependencies_tree[item]:
45
                    self._stats.get_plugin(dependency).update()
46
            # Update the plugin stats
47
            self._stats.get_plugin(item).update()
48
            return self._stats.get_plugin(item)
49
        raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'")
50
51
    def plugins(self):
52
        """Return the list of available plugins."""
53
        return self._stats.getPluginsList()
54
55
    def auto_unit(self, number, low_precision=False, min_symbol='K', none_symbol='-'):
56
        """
57
        Converts a numeric value into a human-readable string with appropriate units.
58
59
        Args:
60
            number (float or int): The numeric value to be converted.
61
            low_precision (bool, optional): If True, use lower precision for the output. Defaults to False.
62
            min_symbol (str, optional): The minimum unit symbol to use (e.g., 'K' for kilo). Defaults to 'K'.
63
            none_symbol (str, optional): The symbol to display if the number is None. Defaults to '-'.
64
65
        Returns:
66
            str: A human-readable string representation of the number with units.
67
        """
68
        return auto_unit(number, low_precision, min_symbol, none_symbol)
69
70
    def bar(self, value, size=18, bar_char='■', empty_char='□', pre_char='', post_char=''):
71
        """
72
        Generate a progress bar representation for a given value.
73
74
        Args:
75
            value (float): The percentage value to represent in the bar (typically between 0 and 100).
76
            size (int, optional): The total length of the bar in characters. Defaults to 18.
77
            bar_char (str, optional): The character used to represent the filled portion of the bar. Defaults to '■'.
78
            empty_char (str, optional): The character used to represent the empty portion of the bar. Defaults to '□'.
79
            pre_char (str, optional): A string to prepend to the bar. Defaults to ''.
80
            post_char (str, optional): A string to append to the bar. Defaults to ''.
81
82
        Returns:
83
            str: A string representing the progress bar.
84
        """
85
        b = Bar(
86
            size, bar_char=bar_char, empty_char=empty_char, pre_char=pre_char, post_char=post_char, display_value=False
87
        )
88
        b.percent = value
89
        return b.get()
90
91
    def top_process(self, limit=3, sorted_by='cpu_percent', sorted_by_secondary='memory_percent'):
92
        """
93
        Returns a list of the top processes sorted by specified criteria.
94
95
        Args:
96
            limit (int, optional): The maximum number of top processes to return. Defaults to 3.
97
            sorted_by (str, optional): The primary key to sort processes by (e.g., 'cpu_percent').
98
                                       Defaults to 'cpu_percent'.
99
            sorted_by_secondary (str, optional): The secondary key to sort processes by if primary keys are equal
100
                                                 (e.g., 'memory_percent'). Defaults to 'memory_percent'.
101
102
        Returns:
103
            list: A list of dictionaries representing the top processes, excluding those with 'glances' in their
104
                  command line.
105
106
        Note:
107
            The 'glances' process is excluded from the returned list to avoid self-generated CPU load affecting
108
            the results.
109
        """
110
        # Exclude glances process from the top list
111
        # because in fetch mode, Glances generate a CPU load
112
        all_but_glances = [p for p in self._stats.get_plugin('processlist').get_raw() if 'glances' not in p['cmdline']]
113
        return sort_stats(all_but_glances, sorted_by=sorted_by, sorted_by_secondary=sorted_by_secondary)[:limit]
114