From acb5ef585f62d506f6f0345b306fc6bc9c15fef4 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Thu, 16 May 2024 17:31:42 +0530 Subject: [PATCH 01/14] chore: ruff cleanup --- docs/conf.py | 35 ++++------- glances/client.py | 5 +- glances/exports/glances_restful/__init__.py | 1 - glances/folder_list.py | 1 + glances/globals.py | 8 --- glances/main.py | 6 +- glances/outdated.py | 6 +- glances/outputs/glances_curses.py | 1 + glances/outputs/glances_restful_api.py | 2 +- glances/outputs/glances_stdout_apidoc.py | 4 +- glances/outputs/glances_unicode.py | 16 ++--- glances/plugins/connections/__init__.py | 1 + glances/plugins/containers/engines/docker.py | 1 + glances/plugins/containers/engines/podman.py | 1 + glances/plugins/diskio/__init__.py | 1 + glances/plugins/folders/__init__.py | 1 + glances/plugins/fs/__init__.py | 3 +- glances/plugins/help/__init__.py | 1 + glances/plugins/network/__init__.py | 1 + glances/plugins/sensors/__init__.py | 4 +- glances/snmp.py | 4 +- pyproject.toml | 18 +++--- run.py | 1 + setup.py | 38 ++++++++---- unittest-core.py | 63 ++++++++++++-------- unittest-restful.py | 28 ++++++--- 26 files changed, 144 insertions(+), 107 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 51f800db..0a4594b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -125,8 +125,7 @@ html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -html_theme_options = { -} +html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] @@ -166,14 +165,7 @@ html_static_path = ['_static'] # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -html_sidebars = { - '**': [ - 'about.html', - 'navigation.html', - 'links.html', - 'searchbox.html' - ] -} +html_sidebars = {'**': ['about.html', 'navigation.html', 'links.html', 'searchbox.html']} # Additional templates that should be rendered to pages, maps page names to # template names. @@ -227,13 +219,10 @@ htmlhelp_basename = 'Glancesdoc' latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # 'preamble': '', - # Latex figure (float) alignment # 'figure_align': 'htbp', } @@ -242,8 +231,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Glances.tex', 'Glances Documentation', - 'Nicolas Hennion', 'manual'), + (master_doc, 'Glances.tex', 'Glances Documentation', 'Nicolas Hennion', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -271,10 +259,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('glances', 'glances', 'An eye on your system', - '', 1) -] +man_pages = [('glances', 'glances', 'An eye on your system', '', 1)] # If true, show URL addresses after external links. # man_show_urls = False @@ -286,9 +271,15 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Glances', 'Glances Documentation', - author, 'Glances', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + 'Glances', + 'Glances Documentation', + author, + 'Glances', + 'One line description of project.', + 'Miscellaneous', + ), ] # Documents to append as an appendix to all manuals. diff --git a/glances/client.py b/glances/client.py index ed020ef5..6b8d4033 100644 --- a/glances/client.py +++ b/glances/client.py @@ -122,8 +122,9 @@ class GlancesClient(object): else: self.log_and_exit( ( - 'Client and server not compatible: ' - 'Client version: {} / Server version: {}'.format(__version__, client_version) + 'Client and server not compatible: ' 'Client version: {} / Server version: {}'.format( + __version__, client_version + ) ) ) return False diff --git a/glances/exports/glances_restful/__init__.py b/glances/exports/glances_restful/__init__.py index 4c674d49..c983dfb9 100644 --- a/glances/exports/glances_restful/__init__.py +++ b/glances/exports/glances_restful/__init__.py @@ -9,7 +9,6 @@ """RESTful interface class.""" - from glances.globals import listkeys from glances.logger import logger from glances.exports.export import GlancesExport diff --git a/glances/folder_list.py b/glances/folder_list.py index aaa79575..f8d771f6 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -8,6 +8,7 @@ # """Manage the folder list.""" + from __future__ import unicode_literals diff --git a/glances/globals.py b/glances/globals.py index 6039f868..7e1d2721 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -19,8 +19,6 @@ import sys import platform import ujson from operator import itemgetter, methodcaller -import unicodedata -import types import subprocess from datetime import datetime import re @@ -28,14 +26,8 @@ import base64 import functools import weakref -import queue -from configparser import ConfigParser, NoOptionError, NoSectionError from statistics import mean -from xmlrpc.client import Fault, ProtocolError, ServerProxy, Transport, Server -from xmlrpc.server import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer from urllib.request import urlopen, Request -from urllib.error import HTTPError, URLError -from urllib.parse import urlparse # Correct issue #1025 by monkey path the xmlrpc lib from defusedxml.xmlrpc import monkey_patch diff --git a/glances/main.py b/glances/main.py index 27d0c982..f8423ea4 100644 --- a/glances/main.py +++ b/glances/main.py @@ -241,7 +241,7 @@ Examples of use: ) parser.add_argument( '--enable-irq', action='store_true', default=False, dest='enable_irq', help='enable IRQ module' - ), + ) parser.add_argument( '--enable-process-extended', action='store_true', @@ -255,14 +255,14 @@ Examples of use: default=True, dest='enable_separator', help='disable separator in the UI (between top and others modules)', - ), + ) parser.add_argument( '--disable-cursor', action='store_true', default=False, dest='disable_cursor', help='disable cursor (process selection) in the UI', - ), + ) # Sort processes list parser.add_argument( '--sort-processes', diff --git a/glances/outdated.py b/glances/outdated.py index 40574327..a7eab6ac 100644 --- a/glances/outdated.py +++ b/glances/outdated.py @@ -46,7 +46,7 @@ class Outdated(object): self.cache_file = os.path.join(self.cache_dir, 'glances-version.db') # Set default value... - self.data = {u'installed_version': __version__, u'latest_version': '0.0', u'refresh_date': datetime.now()} + self.data = {'installed_version': __version__, 'latest_version': '0.0', 'refresh_date': datetime.now()} # Disable update check if `packaging` is not installed if not PACKAGING_IMPORT: @@ -154,14 +154,14 @@ class Outdated(object): logger.debug("Get latest Glances version from the PyPI RESTful API ({})".format(PYPI_API_URL)) # Update the current time - self.data[u'refresh_date'] = datetime.now() + self.data['refresh_date'] = datetime.now() try: res = urlopen(PYPI_API_URL, timeout=3).read() except (HTTPError, URLError, CertificateError) as e: logger.debug("Cannot get Glances version from the PyPI RESTful API ({})".format(e)) else: - self.data[u'latest_version'] = json.loads(nativestr(res))['info']['version'] + self.data['latest_version'] = json.loads(nativestr(res))['info']['version'] logger.debug("Save Glances version to the cache file") # Save result to the cache file diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 9d5ae178..9ab59606 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -8,6 +8,7 @@ # """Curses interface class.""" + from __future__ import unicode_literals import sys diff --git a/glances/outputs/glances_restful_api.py b/glances/outputs/glances_restful_api.py index c07ccba9..1fed6bf9 100644 --- a/glances/outputs/glances_restful_api.py +++ b/glances/outputs/glances_restful_api.py @@ -16,7 +16,7 @@ from io import open import webbrowser from urllib.parse import urljoin -try: +try: from typing import Annotated except ImportError: # Only for Python 3.8 diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 7023617f..aa6b2465 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -75,9 +75,7 @@ WebUI refresh It is possible to change the Web UI refresh rate (default is 2 seconds) using the following option in the URL: ``http://localhost:61208/glances/?refresh=5`` -""".format( - api_version=__apiversion__ -) +""".format(api_version=__apiversion__) def indent_stat(stat, indent=' '): diff --git a/glances/outputs/glances_unicode.py b/glances/outputs/glances_unicode.py index 1e369de3..76ae3e60 100644 --- a/glances/outputs/glances_unicode.py +++ b/glances/outputs/glances_unicode.py @@ -10,14 +10,14 @@ """Manage unicode message for Glances output.""" _unicode_message = { - 'ARROW_LEFT': [u'\u2190', u'<'], - 'ARROW_RIGHT': [u'\u2192', u'>'], - 'ARROW_UP': [u'\u2191', u'^'], - 'ARROW_DOWN': [u'\u2193', u'v'], - 'CHECK': [u'\u2713', u''], - 'PROCESS_SELECTOR': [u'>', u'>'], - 'MEDIUM_LINE': [u'\u23AF', u'-'], - 'LOW_LINE': [u'\u2581', u'_'], + 'ARROW_LEFT': ['\u2190', '<'], + 'ARROW_RIGHT': ['\u2192', '>'], + 'ARROW_UP': ['\u2191', '^'], + 'ARROW_DOWN': ['\u2193', 'v'], + 'CHECK': ['\u2713', ''], + 'PROCESS_SELECTOR': ['>', '>'], + 'MEDIUM_LINE': ['\u23af', '-'], + 'LOW_LINE': ['\u2581', '_'], } diff --git a/glances/plugins/connections/__init__.py b/glances/plugins/connections/__init__.py index 61781ecc..e9b49116 100644 --- a/glances/plugins/connections/__init__.py +++ b/glances/plugins/connections/__init__.py @@ -8,6 +8,7 @@ # """Connections plugin.""" + from __future__ import unicode_literals from glances.logger import logger diff --git a/glances/plugins/containers/engines/docker.py b/glances/plugins/containers/engines/docker.py index b3a6a483..fae29a1d 100644 --- a/glances/plugins/containers/engines/docker.py +++ b/glances/plugins/containers/engines/docker.py @@ -8,6 +8,7 @@ # """Docker Extension unit for Glances' Containers plugin.""" + import time from glances.globals import iterkeys, itervalues, nativestr, pretty_date, replace_special_chars diff --git a/glances/plugins/containers/engines/podman.py b/glances/plugins/containers/engines/podman.py index ab016a9e..70572938 100644 --- a/glances/plugins/containers/engines/podman.py +++ b/glances/plugins/containers/engines/podman.py @@ -7,6 +7,7 @@ # SPDX-License-Identifier: LGPL-3.0-only """Podman Extension unit for Glances' Containers plugin.""" + from datetime import datetime from glances.globals import iterkeys, itervalues, nativestr, pretty_date, string_value_to_float, replace_special_chars diff --git a/glances/plugins/diskio/__init__.py b/glances/plugins/diskio/__init__.py index e1293697..8aed84e1 100644 --- a/glances/plugins/diskio/__init__.py +++ b/glances/plugins/diskio/__init__.py @@ -8,6 +8,7 @@ # """Disk I/O plugin.""" + from __future__ import unicode_literals from glances.logger import logger diff --git a/glances/plugins/folders/__init__.py b/glances/plugins/folders/__init__.py index 029069d7..968206ca 100644 --- a/glances/plugins/folders/__init__.py +++ b/glances/plugins/folders/__init__.py @@ -8,6 +8,7 @@ # """Folder plugin.""" + from __future__ import unicode_literals from glances.logger import logger diff --git a/glances/plugins/fs/__init__.py b/glances/plugins/fs/__init__.py index 0aecf250..25b683b3 100644 --- a/glances/plugins/fs/__init__.py +++ b/glances/plugins/fs/__init__.py @@ -8,6 +8,7 @@ # """File system plugin.""" + from __future__ import unicode_literals import operator @@ -166,7 +167,7 @@ class PluginModel(GlancesPluginModel): 'device_name': fs.device, 'fs_type': fs.fstype, # Manage non breaking space (see issue #1065) - 'mnt_point': u(fs.mountpoint).replace(u'\u00A0', ' '), + 'mnt_point': u(fs.mountpoint).replace('\u00a0', ' '), 'size': fs_usage.total, 'used': fs_usage.used, 'free': fs_usage.free, diff --git a/glances/plugins/help/__init__.py b/glances/plugins/help/__init__.py index 0fe571fa..1430447f 100644 --- a/glances/plugins/help/__init__.py +++ b/glances/plugins/help/__init__.py @@ -12,6 +12,7 @@ Help plugin. Just a stupid plugin to display the help screen. """ + import sys from glances.globals import iteritems from glances import __version__, psutil_version diff --git a/glances/plugins/network/__init__.py b/glances/plugins/network/__init__.py index 12fea9fb..aa60281e 100644 --- a/glances/plugins/network/__init__.py +++ b/glances/plugins/network/__init__.py @@ -8,6 +8,7 @@ # """Network plugin.""" + from __future__ import unicode_literals from glances.plugins.plugin.model import GlancesPluginModel diff --git a/glances/plugins/sensors/__init__.py b/glances/plugins/sensors/__init__.py index 8634d579..8aed0e94 100644 --- a/glances/plugins/sensors/__init__.py +++ b/glances/plugins/sensors/__init__.py @@ -8,6 +8,7 @@ # """Sensors plugin.""" + from enum import Enum from concurrent.futures import ThreadPoolExecutor from typing import List, Dict, Literal, Any @@ -369,8 +370,7 @@ class GlancesGrabSensors(object): sensors_current['label'] = feature.label # Sensors value, limit and unit sensors_current['unit'] = self.sensor_unit - sensors_current['value'] = int( - getattr(feature, 'current', 0) if getattr(feature, 'current', 0) else 0) + sensors_current['value'] = int(getattr(feature, 'current', 0) if getattr(feature, 'current', 0) else 0) system_warning = getattr(feature, 'high', None) system_critical = getattr(feature, 'critical', None) sensors_current['warning'] = int(system_warning) if system_warning is not None else None diff --git a/glances/snmp.py b/glances/snmp.py index aa123151..debfcdb6 100644 --- a/glances/snmp.py +++ b/glances/snmp.py @@ -97,7 +97,7 @@ class GlancesSNMPClient(object): cmdgen.UdpTransportTarget((self.host, self.port)), non_repeaters, max_repetitions, - *oid + *oid, ) if self.version.startswith('2'): errorIndication, errorStatus, errorIndex, varBindTable = self.cmdGen.bulkCmd( @@ -105,7 +105,7 @@ class GlancesSNMPClient(object): cmdgen.UdpTransportTarget((self.host, self.port)), non_repeaters, max_repetitions, - *oid + *oid, ) else: # Bulk request are not available with SNMP version 1 diff --git a/pyproject.toml b/pyproject.toml index 4fe27079..30158d4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,13 @@ skip-string-normalization = true exclude = '\./glances/outputs/static/*' [tool.ruff] +line-length = 120 +target-version = "py38" + +[tool.ruff.format] +quote-style = "preserve" + +[tool.ruff.lint] # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. select = ["E", "F"] ignore = [] @@ -34,18 +41,13 @@ exclude = [ "dist", "node_modules", "venv", - "docs" + "docs", + "./glances/outputs/static/*" ] -# Same as Black. -line-length = 120 - # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -# Assume Python 3.11 -target-version = "py311" - -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 10 \ No newline at end of file diff --git a/run.py b/run.py index 5816aaad..a51fb2e1 100755 --- a/run.py +++ b/run.py @@ -3,6 +3,7 @@ import re import sys from glances import main + if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(main()) diff --git a/setup.py b/setup.py index 7e6e96aa..66a09f5c 100755 --- a/setup.py +++ b/setup.py @@ -32,16 +32,20 @@ with open('README.rst', encoding='utf-8') as f: def get_data_files(): data_files = [ - ('share/doc/glances', ['AUTHORS', 'COPYING', 'NEWS.rst', 'README.rst', "SECURITY.md", - 'CONTRIBUTING.md', 'conf/glances.conf']), - ('share/man/man1', ['docs/man/glances.1']) + ( + 'share/doc/glances', + ['AUTHORS', 'COPYING', 'NEWS.rst', 'README.rst', "SECURITY.md", 'CONTRIBUTING.md', 'conf/glances.conf'], + ), + ('share/man/man1', ['docs/man/glances.1']), ] return data_files + with open('requirements.txt') as f: required = f.read().splitlines() + def get_install_requires(): requires = required if sys.platform.startswith('win'): @@ -59,10 +63,23 @@ def get_install_extras_require(): 'browser': ['zeroconf>=0.19.1'], 'cloud': ['requests'], 'containers': ['docker>=6.1.1', 'python-dateutil', 'six', 'podman', 'packaging'], - 'export': ['bernhard', 'cassandra-driver', 'elasticsearch', 'graphitesender', - 'ibmcloudant', 'influxdb>=1.0.0', 'influxdb-client', 'pymongo', - 'kafka-python', 'pika', 'paho-mqtt', 'potsdb', 'prometheus_client', - 'pyzmq', 'statsd'], + 'export': [ + 'bernhard', + 'cassandra-driver', + 'elasticsearch', + 'graphitesender', + 'ibmcloudant', + 'influxdb>=1.0.0', + 'influxdb-client', + 'pymongo', + 'kafka-python', + 'pika', + 'paho-mqtt', + 'potsdb', + 'prometheus_client', + 'pyzmq', + 'statsd', + ], 'gpu': ['nvidia-ml-py'], 'graph': ['pygal'], 'ip': ['netifaces'], @@ -71,7 +88,7 @@ def get_install_extras_require(): 'snmp': ['pysnmp'], 'sparklines': ['sparklines'], 'web': ['fastapi', 'uvicorn', 'jinja2', 'requests'], - 'wifi': ['wifi'] + 'wifi': ['wifi'], } if sys.platform.startswith('linux'): extras_require['sensors'] = ['batinfo'] @@ -94,6 +111,7 @@ class tests(Command): def run(self): import subprocess import sys + for t in glob.glob('unittest-core.py'): ret = subprocess.call([sys.executable, t]) != 0 if ret != 0: @@ -138,6 +156,6 @@ setup( 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', - 'Topic :: System :: Monitoring' - ] + 'Topic :: System :: Monitoring', + ], ) diff --git a/unittest-core.py b/unittest-core.py index 6e45c0ce..cdaa6ea4 100755 --- a/unittest-core.py +++ b/unittest-core.py @@ -45,8 +45,7 @@ test_config = core.get_config() test_args = core.get_args() # Init Glances stats -stats = GlancesStats(config=test_config, - args=test_args) +stats = GlancesStats(config=test_config, args=test_args) # Unitest class # ============== @@ -78,7 +77,14 @@ class TestGlances(unittest.TestCase): self.assertIsInstance(plugin_instance.get_raw(), (dict, list)) if plugin_instance.history_enable() and isinstance(plugin_instance.get_raw(), dict): self.assertEqual(plugin_instance.get_key(), None) - self.assertTrue(all([f in [h['name'] for h in plugin_instance.items_history_list] for f in plugin_instance.get_raw_history()])) + self.assertTrue( + all( + [ + f in [h['name'] for h in plugin_instance.items_history_list] + for f in plugin_instance.get_raw_history() + ] + ) + ) elif plugin_instance.history_enable() and isinstance(plugin_instance.get_raw(), list): self.assertNotEqual(plugin_instance.get_key(), None) @@ -135,11 +141,17 @@ class TestGlances(unittest.TestCase): if isinstance(plugin_instance.get_raw(), dict): first_history_field = plugin_instance.get_items_history_list()[0]['name'] elif isinstance(plugin_instance.get_raw(), list): - first_history_field = '_'.join([plugin_instance.get_raw()[0][plugin_instance.get_key()], - plugin_instance.get_items_history_list()[0]['name']]) + first_history_field = '_'.join( + [ + plugin_instance.get_raw()[0][plugin_instance.get_key()], + plugin_instance.get_items_history_list()[0]['name'], + ] + ) self.assertEqual(len(plugin_instance.get_raw_history(first_history_field)), 2) - self.assertGreater(plugin_instance.get_raw_history(first_history_field)[1][0], - plugin_instance.get_raw_history(first_history_field)[0][0]) + self.assertGreater( + plugin_instance.get_raw_history(first_history_field)[1][0], + plugin_instance.get_raw_history(first_history_field)[0][0], + ) # Update stats (add third element) plugin_instance.update() @@ -158,10 +170,8 @@ class TestGlances(unittest.TestCase): elif isinstance(plugin_instance.get_raw(), list): first_history_field = plugin_instance.get_items_history_list()[0]['name'] first_item = plugin_instance.get_raw()[0][plugin_instance.get_key()] - self.assertIsInstance(plugin_instance.get_views(item=first_item, - key=first_history_field), dict) - self.assertTrue('decoration' in plugin_instance.get_views(item=first_item, - key=first_history_field)) + self.assertIsInstance(plugin_instance.get_views(item=first_item, key=first_history_field), dict) + self.assertTrue('decoration' in plugin_instance.get_views(item=first_item, key=first_history_field)) self.assertIsInstance(json.loads(plugin_instance.get_json_views()), dict) self.assertEqual(json.loads(plugin_instance.get_json_views()), plugin_instance.get_views()) @@ -352,12 +362,14 @@ class TestGlances(unittest.TestCase): def test_016_subsample(self): """Test subsampling function.""" print('INFO: [TEST_016] Subsampling') - for l_test in [([1, 2, 3], 4), - ([1, 2, 3, 4], 4), - ([1, 2, 3, 4, 5, 6, 7], 4), - ([1, 2, 3, 4, 5, 6, 7, 8], 4), - (list(range(1, 800)), 4), - (list(range(1, 8000)), 800)]: + for l_test in [ + ([1, 2, 3], 4), + ([1, 2, 3, 4], 4), + ([1, 2, 3, 4, 5, 6, 7], 4), + ([1, 2, 3, 4, 5, 6, 7, 8], 4), + (list(range(1, 800)), 4), + (list(range(1, 8000)), 800), + ]: l_subsample = subsample(l_test[0], l_test[1]) self.assertLessEqual(len(l_subsample), l_test[1]) @@ -501,8 +513,9 @@ class TestGlances(unittest.TestCase): plugins_list = stats.getPluginsList() for plugin in plugins_list: for method in mandatories_methods: - self.assertTrue(hasattr(stats.get_plugin(plugin), method), - msg='{} has no method {}()'.format(plugin, method)) + self.assertTrue( + hasattr(stats.get_plugin(plugin), method), msg='{} has no method {}()'.format(plugin, method) + ) def test_096_views(self): """Test get_views method""" @@ -511,14 +524,14 @@ class TestGlances(unittest.TestCase): for plugin in plugins_list: stats.get_plugin(plugin).get_raw() views_grab = stats.get_plugin(plugin).get_views() - self.assertTrue(isinstance(views_grab, dict), - msg='{} view is not a dict'.format(plugin)) + self.assertTrue(isinstance(views_grab, dict), msg='{} view is not a dict'.format(plugin)) def test_097_attribute(self): """Test GlancesAttribute classes""" print('INFO: [TEST_097] Test attribute') # GlancesAttribute from glances.attribute import GlancesAttribute + a = GlancesAttribute('a', description='ad', history_max_size=3) self.assertEqual(a.name, 'a') self.assertEqual(a.description, 'ad') @@ -542,6 +555,7 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_098] Test history') # GlancesHistory from glances.history import GlancesHistory + h = GlancesHistory() h.add('a', 1, history_max_size=100) h.add('a', 2, history_max_size=100) @@ -633,10 +647,8 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_700] Secure functions') if WINDOWS: - self.assertIn(secure_popen('echo TEST'), ['TEST\n', - 'TEST\r\n']) - self.assertIn(secure_popen('echo TEST1 && echo TEST2'), ['TEST1\nTEST2\n', - 'TEST1\r\nTEST2\r\n']) + self.assertIn(secure_popen('echo TEST'), ['TEST\n', 'TEST\r\n']) + self.assertIn(secure_popen('echo TEST1 && echo TEST2'), ['TEST1\nTEST2\n', 'TEST1\r\nTEST2\r\n']) else: self.assertEqual(secure_popen('echo -n TEST'), 'TEST') self.assertEqual(secure_popen('echo -n TEST1 && echo -n TEST2'), 'TEST1TEST2') @@ -647,6 +659,7 @@ class TestGlances(unittest.TestCase): def test_800_memory_leak(self): """Memory leak check""" import tracemalloc + print('INFO: [TEST_800] Memory leak check') tracemalloc.start() # 3 iterations just to init the stats and fill the memory diff --git a/unittest-restful.py b/unittest-restful.py index bc2dc330..ce88c582 100755 --- a/unittest-restful.py +++ b/unittest-restful.py @@ -43,12 +43,9 @@ class TestGlances(unittest.TestCase): def http_get(self, url, gzip=False): """Make the request""" if gzip: - ret = requests.get(url, - stream=True, - headers={'Accept-encoding': 'gzip'}) + ret = requests.get(url, stream=True, headers={'Accept-encoding': 'gzip'}) else: - ret = requests.get(url, - headers={'Accept-encoding': 'identity'}) + ret = requests.get(url, headers={'Accept-encoding': 'identity'}) return ret def test_000_start_server(self): @@ -102,9 +99,24 @@ class TestGlances(unittest.TestCase): self.assertTrue(req.ok) if p in ('uptime', 'version', 'psutilversion'): self.assertIsInstance(req.json(), text_type) - elif p in ('fs', 'percpu', 'sensors', 'alert', 'processlist', 'diskio', - 'hddtemp', 'batpercent', 'network', 'folders', 'amps', 'ports', - 'irq', 'wifi', 'gpu', 'containers'): + elif p in ( + 'fs', + 'percpu', + 'sensors', + 'alert', + 'processlist', + 'diskio', + 'hddtemp', + 'batpercent', + 'network', + 'folders', + 'amps', + 'ports', + 'irq', + 'wifi', + 'gpu', + 'containers', + ): self.assertIsInstance(req.json(), list) if len(req.json()) > 0: self.assertIsInstance(req.json()[0], dict) From 9890749d8101ee94cad1254e0349bde0ff3b2722 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 02:11:23 +0530 Subject: [PATCH 02/14] add: pre-commit - setup changes --- .pre-commit-config.yaml | 22 ++++++++++++++++++++++ dev-requirements.txt | 24 ++++++++++++------------ doc-requirements.txt | 4 ++-- docker-requirements.txt | 4 ++-- optional-requirements.txt | 4 ++-- requirements.txt | 2 +- webui-requirements.txt | 2 +- 7 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..b834ea23 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-ast + - id: check-docstring-first + - id: check-json + - id: check-merge-conflict + - id: check-shebang-scripts-are-executable + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: detect-private-key + - id: mixed-line-ending + - id: requirements-txt-fixer + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.4 + hooks: + - id: ruff-format + - id: ruff + args: [--fix, --exit-non-zero-on-fix] \ No newline at end of file diff --git a/dev-requirements.txt b/dev-requirements.txt index 502cec3c..66534b2f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,17 +1,17 @@ -py-spy -gprof2dot -black -pyright -requirements-parser -flake8 -autopep8 autoflake -ruff +autopep8 +black codespell -memory-profiler +flake8 +fonttools>=4.43.0 # not directly required, pinned by Snyk to avoid a vulnerability +gprof2dot matplotlib -semgrep -setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability +memory-profiler numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability pillow>=10.0.1 # not directly required, pinned by Snyk to avoid a vulnerability -fonttools>=4.43.0 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file +py-spy +pyright +requirements-parser +ruff +semgrep +setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability diff --git a/doc-requirements.txt b/doc-requirements.txt index 65a52334..804d5398 100644 --- a/doc-requirements.txt +++ b/doc-requirements.txt @@ -1,5 +1,5 @@ +reuse +setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability sphinx sphinx_rtd_theme ujson -reuse -setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file diff --git a/docker-requirements.txt b/docker-requirements.txt index 53d88681..feac4040 100644 --- a/docker-requirements.txt +++ b/docker-requirements.txt @@ -2,9 +2,9 @@ -r requirements.txt docker>=6.1.1; python_version >= "3.7" -podman; python_version >= "3.6" packaging; python_version >= "3.7" +podman; python_version >= "3.6" python-dateutil +requests six urllib3 -requests diff --git a/optional-requirements.txt b/optional-requirements.txt index 6585466d..d9d86a1b 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -15,6 +15,7 @@ influxdb-client; python_version >= "3.7" # For InfluxDB >= 1.8 jinja2 kafka-python netifaces +nvidia-ml-py; python_version >= "3.5" packaging; python_version >= "3.7" paho-mqtt pika @@ -26,9 +27,8 @@ pydantic pygal pymdstat pymongo; python_version >= "3.7" -nvidia-ml-py; python_version >= "3.5" -pysnmp-lextudio; python_version >= "3.7" pySMART.smartx +pysnmp-lextudio; python_version >= "3.7" python-dateutil pyzmq requests diff --git a/requirements.txt b/requirements.txt index 8581289d..1b01d13b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -psutil>=5.6.7 defusedxml packaging +psutil>=5.6.7 ujson>=5.4.0 diff --git a/webui-requirements.txt b/webui-requirements.txt index 1b9deb0e..db85591a 100644 --- a/webui-requirements.txt +++ b/webui-requirements.txt @@ -2,5 +2,5 @@ -r requirements.txt fastapi; python_version >= "3.8" +jinja2 uvicorn; python_version >= "3.8" -jinja2 \ No newline at end of file From d392caf6f65286f6b6a38b0f5b28adb391c28ac8 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 02:23:53 +0530 Subject: [PATCH 03/14] chg: ruff - isort fixes --- docs/conf.py | 3 +-- glances/__init__.py | 2 +- glances/actions.py | 2 +- glances/amps/amp.py | 2 +- glances/amps/default/__init__.py | 6 ++--- glances/amps/nginx/__init__.py | 2 +- glances/amps/systemd/__init__.py | 6 ++--- glances/amps/systemv/__init__.py | 6 ++--- glances/amps_list.py | 2 +- glances/autodiscover.py | 3 ++- glances/client.py | 5 ++-- glances/client_browser.py | 11 ++++---- glances/config.py | 8 +++--- glances/cpu_percent.py | 4 +-- glances/events_list.py | 4 +-- glances/exports/export.py | 5 ++-- glances/exports/glances_cassandra/__init__.py | 8 +++--- glances/exports/glances_couchdb/__init__.py | 6 ++--- glances/exports/glances_csv/__init__.py | 4 +-- .../exports/glances_elasticsearch/__init__.py | 6 ++--- glances/exports/glances_graph/__init__.py | 15 ++++++----- glances/exports/glances_graphite/__init__.py | 6 ++--- glances/exports/glances_influxdb/__init__.py | 6 ++--- glances/exports/glances_influxdb2/__init__.py | 6 ++--- glances/exports/glances_json/__init__.py | 4 +-- glances/exports/glances_kafka/__init__.py | 8 +++--- glances/exports/glances_mongodb/__init__.py | 8 +++--- glances/exports/glances_mqtt/__init__.py | 8 +++--- glances/exports/glances_opentsdb/__init__.py | 6 ++--- .../exports/glances_prometheus/__init__.py | 6 ++--- glances/exports/glances_rabbitmq/__init__.py | 6 ++--- glances/exports/glances_restful/__init__.py | 6 ++--- glances/exports/glances_riemann/__init__.py | 6 ++--- glances/exports/glances_statsd/__init__.py | 6 ++--- glances/exports/glances_zeromq/__init__.py | 9 +++---- glances/folder_list.py | 5 ++-- glances/globals.py | 22 ++++++++-------- glances/logger.py | 7 +++-- glances/main.py | 6 ++--- glances/outdated.py | 8 +++--- glances/outputs/glances_curses.py | 8 +++--- glances/outputs/glances_curses_browser.py | 4 +-- glances/outputs/glances_restful_api.py | 12 ++++----- glances/outputs/glances_sparklines.py | 7 ++--- glances/outputs/glances_stdout.py | 2 +- glances/outputs/glances_stdout_apidoc.py | 5 ++-- glances/outputs/glances_stdout_issue.py | 10 +++---- glances/password.py | 2 +- glances/plugins/amps/__init__.py | 2 +- glances/plugins/cloud/__init__.py | 2 +- glances/plugins/connections/__init__.py | 6 ++--- glances/plugins/containers/engines/docker.py | 2 +- glances/plugins/containers/engines/podman.py | 2 +- glances/plugins/core/__init__.py | 4 +-- glances/plugins/cpu/__init__.py | 6 ++--- glances/plugins/diskio/__init__.py | 8 +++--- glances/plugins/folders/__init__.py | 5 ++-- glances/plugins/fs/__init__.py | 6 ++--- glances/plugins/gpu/__init__.py | 2 +- glances/plugins/gpu/cards/amd.py | 2 +- glances/plugins/gpu/cards/nvidia.py | 2 +- glances/plugins/help/__init__.py | 7 ++--- glances/plugins/ip/__init__.py | 4 +-- glances/plugins/irq/__init__.py | 7 +++-- glances/plugins/load/__init__.py | 3 ++- glances/plugins/mem/__init__.py | 4 +-- glances/plugins/memswap/__init__.py | 8 +++--- glances/plugins/network/__init__.py | 6 ++--- glances/plugins/now/__init__.py | 3 ++- glances/plugins/plugin/model.py | 9 +++---- glances/plugins/ports/__init__.py | 12 ++++----- glances/plugins/processcount/__init__.py | 2 +- glances/plugins/processlist/__init__.py | 6 ++--- glances/plugins/quicklook/__init__.py | 8 +++--- glances/plugins/sensors/__init__.py | 14 +++++----- .../sensors/sensor/glances_batpercent.py | 2 +- glances/plugins/smart/__init__.py | 4 +-- glances/plugins/system/__init__.py | 2 +- glances/plugins/uptime/__init__.py | 4 +-- glances/plugins/wifi/__init__.py | 4 +-- glances/ports_list.py | 2 +- glances/processes.py | 13 +++++----- glances/secure.py | 2 +- glances/server.py | 3 +-- glances/standalone.py | 13 +++++----- glances/stats.py | 4 +-- glances/stats_client.py | 2 +- glances/stats_client_snmp.py | 2 +- glances/stats_server.py | 2 +- glances/timer.py | 2 +- glances/webserver.py | 2 +- pyproject.toml | 17 ++++++++++-- run.py | 1 + setup.py | 2 +- unittest-core.py | 26 ++++++++++--------- unittest-restful.py | 8 +++--- unittest-xmlrpc.py | 2 +- 97 files changed, 286 insertions(+), 274 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0a4594b3..5cdfc920 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,8 +12,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os +import sys from datetime import datetime # If extensions (or modules to document with autodoc) are in another directory, @@ -27,7 +27,6 @@ sys.path.insert(0, os.path.abspath('..')) # WARNING: Do not move this import before the sys.path.insert() call. from glances import __version__ - # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. diff --git a/glances/__init__.py b/glances/__init__.py index a8d3ce28..a96d0a06 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -11,11 +11,11 @@ """Init the Glances software.""" # Import system libs -import tracemalloc import locale import platform import signal import sys +import tracemalloc # Global name # Version should start and end with a numerical char diff --git a/glances/actions.py b/glances/actions.py index f61475cb..192749b2 100644 --- a/glances/actions.py +++ b/glances/actions.py @@ -10,8 +10,8 @@ """Manage on alert actions.""" from glances.logger import logger -from glances.timer import Timer from glances.secure import secure_popen +from glances.timer import Timer try: import chevron diff --git a/glances/amps/amp.py b/glances/amps/amp.py index 373d75a4..b34063af 100644 --- a/glances/amps/amp.py +++ b/glances/amps/amp.py @@ -23,8 +23,8 @@ If the *one_line* var is true then the AMP will be displayed in one line. """ from glances.globals import u -from glances.timer import Timer from glances.logger import logger +from glances.timer import Timer class GlancesAmp(object): diff --git a/glances/amps/default/__init__.py b/glances/amps/default/__init__.py index 886f0c8a..444ce053 100644 --- a/glances/amps/default/__init__.py +++ b/glances/amps/default/__init__.py @@ -25,11 +25,11 @@ one_line=false command=foo status """ -from subprocess import check_output, STDOUT, CalledProcessError +from subprocess import STDOUT, CalledProcessError, check_output -from glances.globals import u, to_ascii -from glances.logger import logger from glances.amps.amp import GlancesAmp +from glances.globals import to_ascii, u +from glances.logger import logger class Amp(GlancesAmp): diff --git a/glances/amps/nginx/__init__.py b/glances/amps/nginx/__init__.py index 770c4aca..e8ecb829 100644 --- a/glances/amps/nginx/__init__.py +++ b/glances/amps/nginx/__init__.py @@ -46,8 +46,8 @@ status_url=http://localhost/nginx_status import requests -from glances.logger import logger from glances.amps.amp import GlancesAmp +from glances.logger import logger class Amp(GlancesAmp): diff --git a/glances/amps/systemd/__init__.py b/glances/amps/systemd/__init__.py index 3df7a8ae..f1b8013f 100644 --- a/glances/amps/systemd/__init__.py +++ b/glances/amps/systemd/__init__.py @@ -35,11 +35,11 @@ one_line=true systemctl_cmd=/usr/bin/systemctl --plain """ -from subprocess import check_output, CalledProcessError +from subprocess import CalledProcessError, check_output -from glances.logger import logger -from glances.globals import iteritems, to_ascii from glances.amps.amp import GlancesAmp +from glances.globals import iteritems, to_ascii +from glances.logger import logger class Amp(GlancesAmp): diff --git a/glances/amps/systemv/__init__.py b/glances/amps/systemv/__init__.py index 78df6795..ce5676a1 100644 --- a/glances/amps/systemv/__init__.py +++ b/glances/amps/systemv/__init__.py @@ -34,11 +34,11 @@ one_line=true service_cmd=/usr/bin/service --status-all """ -from subprocess import check_output, STDOUT +from subprocess import STDOUT, check_output -from glances.logger import logger -from glances.globals import iteritems from glances.amps.amp import GlancesAmp +from glances.globals import iteritems +from glances.logger import logger class Amp(GlancesAmp): diff --git a/glances/amps_list.py b/glances/amps_list.py index 5e8c3c13..9feccb5f 100644 --- a/glances/amps_list.py +++ b/glances/amps_list.py @@ -13,7 +13,7 @@ import os import re import threading -from glances.globals import listkeys, iteritems, amps_path +from glances.globals import amps_path, iteritems, listkeys from glances.logger import logger from glances.processes import glances_processes diff --git a/glances/autodiscover.py b/glances/autodiscover.py index f4b0e21a..336af140 100644 --- a/glances/autodiscover.py +++ b/glances/autodiscover.py @@ -16,7 +16,8 @@ from glances.globals import BSD from glances.logger import logger try: - from zeroconf import __version__ as __zeroconf_version, ServiceBrowser, ServiceInfo, Zeroconf + from zeroconf import ServiceBrowser, ServiceInfo, Zeroconf + from zeroconf import __version__ as __zeroconf_version zeroconf_tag = True except ImportError: diff --git a/glances/client.py b/glances/client.py index 6b8d4033..1412d1e1 100644 --- a/glances/client.py +++ b/glances/client.py @@ -9,16 +9,17 @@ """Manage the Glances client.""" -import ujson import socket import sys import time +import ujson + from glances import __version__ from glances.globals import Fault, ProtocolError, ServerProxy, Transport from glances.logger import logger -from glances.stats_client import GlancesStatsClient from glances.outputs.glances_curses import GlancesCursesClient +from glances.stats_client import GlancesStatsClient from glances.timer import Counter diff --git a/glances/client_browser.py b/glances/client_browser.py index 7513664e..c8ba9a8a 100644 --- a/glances/client_browser.py +++ b/glances/client_browser.py @@ -9,17 +9,18 @@ """Manage the Glances client browser (list of Glances server).""" -import ujson import socket import threading -from glances.globals import Fault, ProtocolError, ServerProxy +import ujson + +from glances.autodiscover import GlancesAutoDiscoverServer from glances.client import GlancesClient, GlancesClientTransport -from glances.logger import logger, LOG_FILENAME +from glances.globals import Fault, ProtocolError, ServerProxy +from glances.logger import LOG_FILENAME, logger +from glances.outputs.glances_curses_browser import GlancesCursesBrowser from glances.password_list import GlancesPasswordList as GlancesPassword from glances.static_list import GlancesStaticServer -from glances.autodiscover import GlancesAutoDiscoverServer -from glances.outputs.glances_curses_browser import GlancesCursesBrowser class GlancesClientBrowser(object): diff --git a/glances/config.py b/glances/config.py index abd1f5c1..8f263296 100644 --- a/glances/config.py +++ b/glances/config.py @@ -9,13 +9,13 @@ """Manage the configuration file.""" -import os -import sys import multiprocessing -from io import open +import os import re +import sys +from io import open -from glances.globals import ConfigParser, NoOptionError, NoSectionError, system_exec, BSD, LINUX, MACOS, SUNOS, WINDOWS +from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, ConfigParser, NoOptionError, NoSectionError, system_exec from glances.logger import logger diff --git a/glances/cpu_percent.py b/glances/cpu_percent.py index 78950d0a..f978f863 100644 --- a/glances/cpu_percent.py +++ b/glances/cpu_percent.py @@ -9,11 +9,11 @@ """CPU percent stats shared between CPU and Quicklook plugins.""" +import psutil + from glances.logger import logger from glances.timer import Timer -import psutil - class CpuPercent(object): """Get and store the CPU percent.""" diff --git a/glances/events_list.py b/glances/events_list.py index 04f6459d..b50ec83f 100644 --- a/glances/events_list.py +++ b/glances/events_list.py @@ -10,12 +10,12 @@ """Manage Glances events list (previously Glances logs in Glances < 3.1).""" import time -from datetime import datetime from dataclasses import asdict +from datetime import datetime +from glances.event import GlancesEvent from glances.processes import glances_processes from glances.thresholds import glances_thresholds -from glances.event import GlancesEvent # Static decision tree for the global alert message # - msg: Message to be displayed (result of the decision tree) diff --git a/glances/exports/export.py b/glances/exports/export.py index 12f8d8b0..4b57a122 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -13,10 +13,9 @@ I am your father... ...for all Glances exports IF. """ -from glances.globals import json_dumps -from glances.globals import NoOptionError, NoSectionError, iteritems, iterkeys -from glances.timer import Counter +from glances.globals import NoOptionError, NoSectionError, iteritems, iterkeys, json_dumps from glances.logger import logger +from glances.timer import Counter class GlancesExport(object): diff --git a/glances/exports/glances_cassandra/__init__.py b/glances/exports/glances_cassandra/__init__.py index 0d993ab2..75f591b7 100644 --- a/glances/exports/glances_cassandra/__init__.py +++ b/glances/exports/glances_cassandra/__init__.py @@ -13,13 +13,13 @@ import sys from datetime import datetime from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - +from cassandra import InvalidRequest from cassandra.auth import PlainTextAuthProvider from cassandra.cluster import Cluster from cassandra.util import uuid_from_time -from cassandra import InvalidRequest + +from glances.exports.export import GlancesExport +from glances.logger import logger class Export(GlancesExport): diff --git a/glances/exports/glances_couchdb/__init__.py b/glances/exports/glances_couchdb/__init__.py index d54e0621..02fd62f6 100644 --- a/glances/exports/glances_couchdb/__init__.py +++ b/glances/exports/glances_couchdb/__init__.py @@ -20,11 +20,11 @@ import sys from datetime import datetime -from glances.logger import logger -from glances.exports.export import GlancesExport - import pycouchdb +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the CouchDB export module.""" diff --git a/glances/exports/glances_csv/__init__.py b/glances/exports/glances_csv/__init__.py index d032680b..a881bdb0 100644 --- a/glances/exports/glances_csv/__init__.py +++ b/glances/exports/glances_csv/__init__.py @@ -9,13 +9,13 @@ """CSV interface class.""" -import os.path import csv +import os.path import sys import time -from glances.logger import logger from glances.exports.export import GlancesExport +from glances.logger import logger class Export(GlancesExport): diff --git a/glances/exports/glances_elasticsearch/__init__.py b/glances/exports/glances_elasticsearch/__init__.py index 447c1281..2ab17074 100644 --- a/glances/exports/glances_elasticsearch/__init__.py +++ b/glances/exports/glances_elasticsearch/__init__.py @@ -12,11 +12,11 @@ import sys from datetime import datetime -from glances.logger import logger -from glances.exports.export import GlancesExport - from elasticsearch import Elasticsearch, helpers +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the ElasticSearch (ES) export module.""" diff --git a/glances/exports/glances_graph/__init__.py b/glances/exports/glances_graph/__init__.py index 87fac2e9..753f2e18 100644 --- a/glances/exports/glances_graph/__init__.py +++ b/glances/exports/glances_graph/__init__.py @@ -9,17 +9,18 @@ """Graph exporter interface class.""" -from pygal import DateTimeLine -import pygal.style -import sys -import os -import tempfile import errno +import os +import sys +import tempfile +import pygal.style +from pygal import DateTimeLine + +from glances.exports.export import GlancesExport +from glances.globals import iteritems, time_serie_subsample from glances.logger import logger from glances.timer import Timer -from glances.globals import iteritems, time_serie_subsample -from glances.exports.export import GlancesExport class Export(GlancesExport): diff --git a/glances/exports/glances_graphite/__init__.py b/glances/exports/glances_graphite/__init__.py index e7f884df..84289238 100644 --- a/glances/exports/glances_graphite/__init__.py +++ b/glances/exports/glances_graphite/__init__.py @@ -12,11 +12,11 @@ import sys from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - from graphitesend import GraphiteClient +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the Graphite export module.""" diff --git a/glances/exports/glances_influxdb/__init__.py b/glances/exports/glances_influxdb/__init__.py index b5df2708..b1bc9a83 100644 --- a/glances/exports/glances_influxdb/__init__.py +++ b/glances/exports/glances_influxdb/__init__.py @@ -12,12 +12,12 @@ import sys from platform import node -from glances.logger import logger -from glances.exports.export import GlancesExport - from influxdb import InfluxDBClient from influxdb.client import InfluxDBClientError +from glances.exports.export import GlancesExport +from glances.logger import logger + FIELD_TO_TAG = ['name', 'cmdline', 'type'] diff --git a/glances/exports/glances_influxdb2/__init__.py b/glances/exports/glances_influxdb2/__init__.py index 6abcfcea..8b8ea964 100644 --- a/glances/exports/glances_influxdb2/__init__.py +++ b/glances/exports/glances_influxdb2/__init__.py @@ -12,11 +12,11 @@ import sys from platform import node -from glances.logger import logger -from glances.exports.export import GlancesExport - from influxdb_client import InfluxDBClient, WriteOptions +from glances.exports.export import GlancesExport +from glances.logger import logger + FIELD_TO_TAG = ['name', 'cmdline', 'type'] diff --git a/glances/exports/glances_json/__init__.py b/glances/exports/glances_json/__init__.py index bab53187..62a3c204 100644 --- a/glances/exports/glances_json/__init__.py +++ b/glances/exports/glances_json/__init__.py @@ -2,9 +2,9 @@ import sys -from glances.globals import listkeys, json_dumps -from glances.logger import logger from glances.exports.export import GlancesExport +from glances.globals import json_dumps, listkeys +from glances.logger import logger class Export(GlancesExport): diff --git a/glances/exports/glances_kafka/__init__.py b/glances/exports/glances_kafka/__init__.py index c024ece5..fc687e9b 100644 --- a/glances/exports/glances_kafka/__init__.py +++ b/glances/exports/glances_kafka/__init__.py @@ -11,12 +11,12 @@ import sys -from glances.logger import logger -from glances.globals import json_dumps -from glances.exports.export import GlancesExport - from kafka import KafkaProducer +from glances.exports.export import GlancesExport +from glances.globals import json_dumps +from glances.logger import logger + class Export(GlancesExport): """This class manages the Kafka export module.""" diff --git a/glances/exports/glances_mongodb/__init__.py b/glances/exports/glances_mongodb/__init__.py index b5a740f1..953b498a 100644 --- a/glances/exports/glances_mongodb/__init__.py +++ b/glances/exports/glances_mongodb/__init__.py @@ -10,12 +10,12 @@ """MongoDB interface class.""" import sys - -from glances.logger import logger -from glances.exports.export import GlancesExport +from urllib.parse import quote_plus import pymongo -from urllib.parse import quote_plus + +from glances.exports.export import GlancesExport +from glances.logger import logger class Export(GlancesExport): diff --git a/glances/exports/glances_mqtt/__init__.py b/glances/exports/glances_mqtt/__init__.py index 45d3b127..55cf8253 100755 --- a/glances/exports/glances_mqtt/__init__.py +++ b/glances/exports/glances_mqtt/__init__.py @@ -13,14 +13,14 @@ import socket import string import sys -from glances.logger import logger -from glances.exports.export import GlancesExport -from glances.globals import json_dumps - # Import paho for MQTT import certifi import paho.mqtt.client as paho +from glances.exports.export import GlancesExport +from glances.globals import json_dumps +from glances.logger import logger + class Export(GlancesExport): """This class manages the MQTT export module.""" diff --git a/glances/exports/glances_opentsdb/__init__.py b/glances/exports/glances_opentsdb/__init__.py index 8628cfde..7b411499 100644 --- a/glances/exports/glances_opentsdb/__init__.py +++ b/glances/exports/glances_opentsdb/__init__.py @@ -12,11 +12,11 @@ import sys from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - import potsdb +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the OpenTSDB export module.""" diff --git a/glances/exports/glances_prometheus/__init__.py b/glances/exports/glances_prometheus/__init__.py index fa1714f6..3a19b113 100644 --- a/glances/exports/glances_prometheus/__init__.py +++ b/glances/exports/glances_prometheus/__init__.py @@ -12,11 +12,11 @@ import sys from numbers import Number -from glances.logger import logger +from prometheus_client import Gauge, start_http_server + from glances.exports.export import GlancesExport from glances.globals import iteritems, listkeys - -from prometheus_client import start_http_server, Gauge +from glances.logger import logger class Export(GlancesExport): diff --git a/glances/exports/glances_rabbitmq/__init__.py b/glances/exports/glances_rabbitmq/__init__.py index 9d4526b4..0cec274e 100644 --- a/glances/exports/glances_rabbitmq/__init__.py +++ b/glances/exports/glances_rabbitmq/__init__.py @@ -14,12 +14,12 @@ import socket import sys from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - # Import pika for RabbitMQ import pika +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the rabbitMQ export module.""" diff --git a/glances/exports/glances_restful/__init__.py b/glances/exports/glances_restful/__init__.py index c983dfb9..1b6ad919 100644 --- a/glances/exports/glances_restful/__init__.py +++ b/glances/exports/glances_restful/__init__.py @@ -9,11 +9,11 @@ """RESTful interface class.""" +from requests import post + +from glances.exports.export import GlancesExport from glances.globals import listkeys from glances.logger import logger -from glances.exports.export import GlancesExport - -from requests import post class Export(GlancesExport): diff --git a/glances/exports/glances_riemann/__init__.py b/glances/exports/glances_riemann/__init__.py index ed5d3e63..79dd2cb8 100644 --- a/glances/exports/glances_riemann/__init__.py +++ b/glances/exports/glances_riemann/__init__.py @@ -12,12 +12,12 @@ import socket from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - # Import bernhard for Riemann import bernhard +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the Riemann export module.""" diff --git a/glances/exports/glances_statsd/__init__.py b/glances/exports/glances_statsd/__init__.py index 3cfa35f9..d65c36ca 100644 --- a/glances/exports/glances_statsd/__init__.py +++ b/glances/exports/glances_statsd/__init__.py @@ -11,11 +11,11 @@ from numbers import Number -from glances.logger import logger -from glances.exports.export import GlancesExport - from statsd import StatsClient +from glances.exports.export import GlancesExport +from glances.logger import logger + class Export(GlancesExport): """This class manages the Statsd export module.""" diff --git a/glances/exports/glances_zeromq/__init__.py b/glances/exports/glances_zeromq/__init__.py index 96ed8a83..26c030f0 100644 --- a/glances/exports/glances_zeromq/__init__.py +++ b/glances/exports/glances_zeromq/__init__.py @@ -11,14 +11,13 @@ import sys -from glances.globals import b -from glances.logger import logger -from glances.exports.export import GlancesExport -from glances.globals import json_dumps - import zmq from zmq.utils.strtypes import asbytes +from glances.exports.export import GlancesExport +from glances.globals import b, json_dumps +from glances.logger import logger + class Export(GlancesExport): """This class manages the ZeroMQ export module.""" diff --git a/glances/folder_list.py b/glances/folder_list.py index f8d771f6..5820e847 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -11,10 +11,9 @@ from __future__ import unicode_literals - -from glances.timer import Timer -from glances.globals import nativestr, folder_size +from glances.globals import folder_size, nativestr from glances.logger import logger +from glances.timer import Timer class FolderList(object): diff --git a/glances/globals.py b/glances/globals.py index 7e1d2721..e18a9f35 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -13,21 +13,21 @@ # GLOBAL IMPORTS ################ -import errno -import os -import sys -import platform -import ujson -from operator import itemgetter, methodcaller -import subprocess -from datetime import datetime -import re import base64 +import errno import functools +import os +import platform +import re +import subprocess +import sys import weakref - +from datetime import datetime +from operator import itemgetter, methodcaller from statistics import mean -from urllib.request import urlopen, Request +from urllib.request import Request, urlopen + +import ujson # Correct issue #1025 by monkey path the xmlrpc lib from defusedxml.xmlrpc import monkey_patch diff --git a/glances/logger.py b/glances/logger.py index 3da96356..67061e35 100644 --- a/glances/logger.py +++ b/glances/logger.py @@ -9,13 +9,12 @@ """Custom logger class.""" -import os -import json import getpass -import tempfile - +import json import logging import logging.config +import os +import tempfile from glances.globals import safe_makedirs diff --git a/glances/main.py b/glances/main.py index f8423ea4..dffc5f5f 100644 --- a/glances/main.py +++ b/glances/main.py @@ -15,11 +15,11 @@ import tempfile from logging import DEBUG from warnings import simplefilter -from glances import __version__, psutil_version, __apiversion__ -from glances.globals import WINDOWS, disable, enable +from glances import __apiversion__, __version__, psutil_version from glances.config import Config +from glances.globals import WINDOWS, disable, enable +from glances.logger import LOG_FILENAME, logger from glances.processes import sort_processes_key_list -from glances.logger import logger, LOG_FILENAME class GlancesMain(object): diff --git a/glances/outdated.py b/glances/outdated.py index a7eab6ac..424e5e7e 100644 --- a/glances/outdated.py +++ b/glances/outdated.py @@ -9,16 +9,16 @@ """Manage Glances update.""" -from datetime import datetime, timedelta -import threading import json -import pickle import os +import pickle +import threading +from datetime import datetime, timedelta from ssl import CertificateError from glances import __version__ -from glances.globals import nativestr, urlopen, HTTPError, URLError, safe_makedirs from glances.config import user_cache_dir +from glances.globals import HTTPError, URLError, nativestr, safe_makedirs, urlopen from glances.logger import logger try: diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 9ab59606..bed7970a 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -11,14 +11,14 @@ from __future__ import unicode_literals -import sys import getpass +import sys -from glances.globals import MACOS, WINDOWS, nativestr, u, itervalues, enable, disable -from glances.logger import logger from glances.events_list import glances_events -from glances.processes import glances_processes, sort_processes_key_list +from glances.globals import MACOS, WINDOWS, disable, enable, itervalues, nativestr, u +from glances.logger import logger from glances.outputs.glances_unicode import unicode_message +from glances.processes import glances_processes, sort_processes_key_list from glances.timer import Timer # Import curses library for "normal" operating system diff --git a/glances/outputs/glances_curses_browser.py b/glances/outputs/glances_curses_browser.py index caa567f4..f2633969 100644 --- a/glances/outputs/glances_curses_browser.py +++ b/glances/outputs/glances_curses_browser.py @@ -9,11 +9,11 @@ """Curses browser interface class .""" -import math import curses -from glances.outputs.glances_curses import _GlancesCurses +import math from glances.logger import logger +from glances.outputs.glances_curses import _GlancesCurses from glances.timer import Timer diff --git a/glances/outputs/glances_restful_api.py b/glances/outputs/glances_restful_api.py index 1fed6bf9..8ef876a0 100644 --- a/glances/outputs/glances_restful_api.py +++ b/glances/outputs/glances_restful_api.py @@ -12,8 +12,8 @@ import os import sys import tempfile -from io import open import webbrowser +from io import open from urllib.parse import urljoin try: @@ -23,20 +23,20 @@ except ImportError: # To be removed when Python 3.8 support will be dropped from typing_extensions import Annotated -from glances import __version__, __apiversion__ +from glances import __apiversion__, __version__ +from glances.logger import logger from glances.password import GlancesPassword from glances.timer import Timer -from glances.logger import logger # FastAPI import try: - from fastapi import FastAPI, Depends, HTTPException, status, APIRouter, Request - from fastapi.security import HTTPBasic, HTTPBasicCredentials + from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request, status from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.gzip import GZipMiddleware from fastapi.responses import HTMLResponse, ORJSONResponse - from fastapi.templating import Jinja2Templates + from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.staticfiles import StaticFiles + from fastapi.templating import Jinja2Templates except ImportError: logger.critical('FastAPI import error. Glances cannot start in web server mode.') sys.exit(2) diff --git a/glances/outputs/glances_sparklines.py b/glances/outputs/glances_sparklines.py index edd482b0..d4ada88c 100644 --- a/glances/outputs/glances_sparklines.py +++ b/glances/outputs/glances_sparklines.py @@ -9,11 +9,12 @@ """Manage sparklines for Glances output.""" -from __future__ import unicode_literals -from __future__ import division +from __future__ import division, unicode_literals + import sys -from glances.logger import logger + from glances.globals import nativestr +from glances.logger import logger sparklines_module = True diff --git a/glances/outputs/glances_stdout.py b/glances/outputs/glances_stdout.py index ec70f55b..817c911b 100644 --- a/glances/outputs/glances_stdout.py +++ b/glances/outputs/glances_stdout.py @@ -11,8 +11,8 @@ import time -from glances.logger import logger from glances.globals import printandflush +from glances.logger import logger class GlancesStdout(object): diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index aa6b2465..907d4929 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -9,14 +9,13 @@ """Fields description interface class.""" -from pprint import pformat import json import time +from pprint import pformat from glances import __apiversion__ -from glances.logger import logger from glances.globals import iteritems - +from glances.logger import logger API_URL = "http://localhost:61208/api/{api_version}".format(api_version=__apiversion__) diff --git a/glances/outputs/glances_stdout_issue.py b/glances/outputs/glances_stdout_issue.py index 3039a7d9..55e2cd41 100644 --- a/glances/outputs/glances_stdout_issue.py +++ b/glances/outputs/glances_stdout_issue.py @@ -10,16 +10,16 @@ """Issue interface class.""" import os -import sys import platform -import time import pprint - -from glances.timer import Counter -from glances import __version__, psutil_version +import sys +import time import psutil + import glances +from glances import __version__, psutil_version +from glances.timer import Counter TERMINAL_WIDTH = 79 diff --git a/glances/password.py b/glances/password.py index d0057630..c4e8280e 100644 --- a/glances/password.py +++ b/glances/password.py @@ -16,8 +16,8 @@ import sys import uuid from io import open -from glances.globals import b, safe_makedirs, weak_lru_cache from glances.config import user_config_dir +from glances.globals import b, safe_makedirs, weak_lru_cache from glances.logger import logger diff --git a/glances/plugins/amps/__init__.py b/glances/plugins/amps/__init__.py index e8d6644a..9e9e46be 100644 --- a/glances/plugins/amps/__init__.py +++ b/glances/plugins/amps/__init__.py @@ -9,8 +9,8 @@ """Monitor plugin.""" -from glances.globals import iteritems from glances.amps_list import AmpsList as glancesAmpsList +from glances.globals import iteritems from glances.plugins.plugin.model import GlancesPluginModel # Fields description diff --git a/glances/plugins/cloud/__init__.py b/glances/plugins/cloud/__init__.py index 72b8dde1..bb9880f8 100644 --- a/glances/plugins/cloud/__init__.py +++ b/glances/plugins/cloud/__init__.py @@ -17,8 +17,8 @@ Supported Cloud API: import threading from glances.globals import iteritems, to_ascii -from glances.plugins.plugin.model import GlancesPluginModel from glances.logger import logger +from glances.plugins.plugin.model import GlancesPluginModel # Import plugin specific dependency try: diff --git a/glances/plugins/connections/__init__.py b/glances/plugins/connections/__init__.py index e9b49116..f11b9aea 100644 --- a/glances/plugins/connections/__init__.py +++ b/glances/plugins/connections/__init__.py @@ -11,11 +11,11 @@ from __future__ import unicode_literals +import psutil + +from glances.globals import nativestr from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel -from glances.globals import nativestr - -import psutil # Fields description # description: human readable description diff --git a/glances/plugins/containers/engines/docker.py b/glances/plugins/containers/engines/docker.py index fae29a1d..a74e2a70 100644 --- a/glances/plugins/containers/engines/docker.py +++ b/glances/plugins/containers/engines/docker.py @@ -18,8 +18,8 @@ from glances.plugins.containers.stats_streamer import StatsStreamer # Docker-py library (optional and Linux-only) # https://github.com/docker/docker-py try: - import requests import docker + import requests from dateutil import parser, tz except Exception as e: import_docker_error_tag = True diff --git a/glances/plugins/containers/engines/podman.py b/glances/plugins/containers/engines/podman.py index 70572938..b98bc540 100644 --- a/glances/plugins/containers/engines/podman.py +++ b/glances/plugins/containers/engines/podman.py @@ -10,7 +10,7 @@ from datetime import datetime -from glances.globals import iterkeys, itervalues, nativestr, pretty_date, string_value_to_float, replace_special_chars +from glances.globals import iterkeys, itervalues, nativestr, pretty_date, replace_special_chars, string_value_to_float from glances.logger import logger from glances.plugins.containers.stats_streamer import StatsStreamer diff --git a/glances/plugins/core/__init__.py b/glances/plugins/core/__init__.py index 2925a7d5..ffede532 100644 --- a/glances/plugins/core/__init__.py +++ b/glances/plugins/core/__init__.py @@ -9,10 +9,10 @@ """CPU core plugin.""" -from glances.plugins.plugin.model import GlancesPluginModel - import psutil +from glances.plugins.plugin.model import GlancesPluginModel + # Fields description fields_description = { 'phys': {'description': 'Number of physical cores (hyper thread CPUs are excluded).', 'unit': 'number'}, diff --git a/glances/plugins/cpu/__init__.py b/glances/plugins/cpu/__init__.py index 45df455f..9379fd09 100644 --- a/glances/plugins/cpu/__init__.py +++ b/glances/plugins/cpu/__init__.py @@ -9,13 +9,13 @@ """CPU plugin.""" -from glances.globals import LINUX, WINDOWS, SUNOS, iterkeys +import psutil + from glances.cpu_percent import cpu_percent +from glances.globals import LINUX, SUNOS, WINDOWS, iterkeys from glances.plugins.core import PluginModel as CorePluginModel from glances.plugins.plugin.model import GlancesPluginModel -import psutil - # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/diskio/__init__.py b/glances/plugins/diskio/__init__.py index 8aed84e1..67ea1205 100644 --- a/glances/plugins/diskio/__init__.py +++ b/glances/plugins/diskio/__init__.py @@ -11,12 +11,12 @@ from __future__ import unicode_literals -from glances.logger import logger -from glances.globals import nativestr -from glances.plugins.plugin.model import GlancesPluginModel - import psutil +from glances.globals import nativestr +from glances.logger import logger +from glances.plugins.plugin.model import GlancesPluginModel + # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/folders/__init__.py b/glances/plugins/folders/__init__.py index 968206ca..9ebb8ea9 100644 --- a/glances/plugins/folders/__init__.py +++ b/glances/plugins/folders/__init__.py @@ -11,12 +11,11 @@ from __future__ import unicode_literals -from glances.logger import logger -from glances.globals import nativestr from glances.folder_list import FolderList as glancesFolderList +from glances.globals import nativestr +from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel - # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/fs/__init__.py b/glances/plugins/fs/__init__.py index 25b683b3..d5affe5b 100644 --- a/glances/plugins/fs/__init__.py +++ b/glances/plugins/fs/__init__.py @@ -13,12 +13,12 @@ from __future__ import unicode_literals import operator -from glances.globals import u, nativestr, PermissionError +import psutil + +from glances.globals import PermissionError, nativestr, u from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel -import psutil - # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/gpu/__init__.py b/glances/plugins/gpu/__init__.py index 804fa45a..47ccf77e 100644 --- a/glances/plugins/gpu/__init__.py +++ b/glances/plugins/gpu/__init__.py @@ -16,8 +16,8 @@ Currently supported: """ from glances.globals import to_fahrenheit -from glances.plugins.gpu.cards.nvidia import NvidiaGPU from glances.plugins.gpu.cards.amd import AmdGPU +from glances.plugins.gpu.cards.nvidia import NvidiaGPU from glances.plugins.plugin.model import GlancesPluginModel # Fields description diff --git a/glances/plugins/gpu/cards/amd.py b/glances/plugins/gpu/cards/amd.py index 74449104..2f8cd562 100644 --- a/glances/plugins/gpu/cards/amd.py +++ b/glances/plugins/gpu/cards/amd.py @@ -35,8 +35,8 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually # └── 0 # └── amdgpu_pm_info -import re import os +import re DRM_ROOT_FOLDER: str = '/sys/class/drm' CARD_REGEX: str = r"^card\d$" diff --git a/glances/plugins/gpu/cards/nvidia.py b/glances/plugins/gpu/cards/nvidia.py index c7a31295..a6473b24 100644 --- a/glances/plugins/gpu/cards/nvidia.py +++ b/glances/plugins/gpu/cards/nvidia.py @@ -9,8 +9,8 @@ """NVidia Extension unit for Glances' GPU plugin.""" -from glances.logger import logger from glances.globals import nativestr +from glances.logger import logger try: import pynvml diff --git a/glances/plugins/help/__init__.py b/glances/plugins/help/__init__.py index 1430447f..6f8c46ac 100644 --- a/glances/plugins/help/__init__.py +++ b/glances/plugins/help/__init__.py @@ -14,11 +14,12 @@ Just a stupid plugin to display the help screen. """ import sys -from glances.globals import iteritems -from glances import __version__, psutil_version -from glances.plugins.plugin.model import GlancesPluginModel from itertools import chain +from glances import __version__, psutil_version +from glances.globals import iteritems +from glances.plugins.plugin.model import GlancesPluginModel + class PluginModel(GlancesPluginModel): """Glances help plugin.""" diff --git a/glances/plugins/ip/__init__.py b/glances/plugins/ip/__init__.py index fe79480e..09c3c6c5 100644 --- a/glances/plugins/ip/__init__.py +++ b/glances/plugins/ip/__init__.py @@ -10,13 +10,13 @@ """IP plugin.""" import threading + from ujson import loads from glances.globals import queue, urlopen_auth from glances.logger import logger -from glances.timer import Timer -from glances.timer import getTimeSinceLastUpdate from glances.plugins.plugin.model import GlancesPluginModel +from glances.timer import Timer, getTimeSinceLastUpdate # Import plugin specific dependency try: diff --git a/glances/plugins/irq/__init__.py b/glances/plugins/irq/__init__.py index bfa70af8..c4c5004c 100644 --- a/glances/plugins/irq/__init__.py +++ b/glances/plugins/irq/__init__.py @@ -9,14 +9,13 @@ """IRQ plugin.""" -import os import operator +import os -from glances.logger import logger from glances.globals import LINUX -from glances.timer import getTimeSinceLastUpdate +from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel - +from glances.timer import getTimeSinceLastUpdate # Fields description # description: human readable description diff --git a/glances/plugins/load/__init__.py b/glances/plugins/load/__init__.py index 910dbb3a..c26446bc 100644 --- a/glances/plugins/load/__init__.py +++ b/glances/plugins/load/__init__.py @@ -10,12 +10,13 @@ """Load plugin.""" import os + import psutil from glances.globals import iteritems +from glances.logger import logger from glances.plugins.core import PluginModel as CorePluginModel from glances.plugins.plugin.model import GlancesPluginModel -from glances.logger import logger # Fields description fields_description = { diff --git a/glances/plugins/mem/__init__.py b/glances/plugins/mem/__init__.py index 44714e11..b462d9ee 100644 --- a/glances/plugins/mem/__init__.py +++ b/glances/plugins/mem/__init__.py @@ -9,10 +9,10 @@ """Virtual memory plugin.""" -from glances.plugins.plugin.model import GlancesPluginModel - import psutil +from glances.plugins.plugin.model import GlancesPluginModel + # Fields description fields_description = { 'total': {'description': 'Total physical memory available.', 'unit': 'bytes', 'min_symbol': 'K'}, diff --git a/glances/plugins/memswap/__init__.py b/glances/plugins/memswap/__init__.py index 8f98a9e3..534848ce 100644 --- a/glances/plugins/memswap/__init__.py +++ b/glances/plugins/memswap/__init__.py @@ -9,12 +9,12 @@ """Swap memory plugin.""" -from glances.globals import iterkeys -from glances.timer import getTimeSinceLastUpdate -from glances.plugins.plugin.model import GlancesPluginModel - import psutil +from glances.globals import iterkeys +from glances.plugins.plugin.model import GlancesPluginModel +from glances.timer import getTimeSinceLastUpdate + # Fields description fields_description = { 'total': {'description': 'Total swap memory.', 'unit': 'bytes', 'min_symbol': 'K'}, diff --git a/glances/plugins/network/__init__.py b/glances/plugins/network/__init__.py index aa60281e..3b5f05f2 100644 --- a/glances/plugins/network/__init__.py +++ b/glances/plugins/network/__init__.py @@ -11,11 +11,11 @@ from __future__ import unicode_literals -from glances.plugins.plugin.model import GlancesPluginModel -from glances.logger import logger - import psutil +from glances.logger import logger +from glances.plugins.plugin.model import GlancesPluginModel + # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/now/__init__.py b/glances/plugins/now/__init__.py index 021ad5b0..8482d70b 100644 --- a/glances/plugins/now/__init__.py +++ b/glances/plugins/now/__init__.py @@ -9,8 +9,9 @@ """Now (current date) plugin.""" -from time import tzname, strftime import datetime +from time import strftime, tzname + from glances.plugins.plugin.model import GlancesPluginModel # Fields description diff --git a/glances/plugins/plugin/model.py b/glances/plugins/plugin/model.py index 99539e1b..42973918 100644 --- a/glances/plugins/plugin/model.py +++ b/glances/plugins/plugin/model.py @@ -13,18 +13,17 @@ I am your father... ...of all Glances model plugins. """ -import re import copy +import re -from glances.globals import iterkeys, itervalues, listkeys, mean, nativestr, json_dumps, json_dumps_dictlist, dictlist from glances.actions import GlancesActions +from glances.events_list import glances_events +from glances.globals import dictlist, iterkeys, itervalues, json_dumps, json_dumps_dictlist, listkeys, mean, nativestr from glances.history import GlancesHistory from glances.logger import logger -from glances.events_list import glances_events +from glances.outputs.glances_unicode import unicode_message from glances.thresholds import glances_thresholds from glances.timer import Counter, Timer, getTimeSinceLastUpdate -from glances.outputs.glances_unicode import unicode_message - fields_unit_short = {'percent': '%'} diff --git a/glances/plugins/ports/__init__.py b/glances/plugins/ports/__init__.py index 4be1d421..87c467fc 100644 --- a/glances/plugins/ports/__init__.py +++ b/glances/plugins/ports/__init__.py @@ -9,19 +9,19 @@ """Ports scanner plugin.""" +import numbers import os +import socket import subprocess import threading -import socket import time -import numbers -from glances.globals import WINDOWS, MACOS, BSD, bool_type -from glances.ports_list import GlancesPortsList -from glances.web_list import GlancesWebList -from glances.timer import Counter +from glances.globals import BSD, MACOS, WINDOWS, bool_type from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel +from glances.ports_list import GlancesPortsList +from glances.timer import Counter +from glances.web_list import GlancesWebList try: import requests diff --git a/glances/plugins/processcount/__init__.py b/glances/plugins/processcount/__init__.py index 6d651e31..53479ead 100644 --- a/glances/plugins/processcount/__init__.py +++ b/glances/plugins/processcount/__init__.py @@ -9,8 +9,8 @@ """Process count plugin.""" -from glances.processes import glances_processes, sort_for_human from glances.plugins.plugin.model import GlancesPluginModel +from glances.processes import glances_processes, sort_for_human # Fields description # description: human readable description diff --git a/glances/plugins/processlist/__init__.py b/glances/plugins/processlist/__init__.py index 831c40a9..b2a4bf2f 100644 --- a/glances/plugins/processlist/__init__.py +++ b/glances/plugins/processlist/__init__.py @@ -9,15 +9,15 @@ """Process list plugin.""" -import os import copy +import os -from glances.logger import logger from glances.globals import WINDOWS, key_exist_value_not_none_not_v, replace_special_chars -from glances.processes import glances_processes, sort_stats +from glances.logger import logger from glances.outputs.glances_unicode import unicode_message from glances.plugins.core import PluginModel as CorePluginModel from glances.plugins.plugin.model import GlancesPluginModel +from glances.processes import glances_processes, sort_stats # Fields description # description: human readable description diff --git a/glances/plugins/quicklook/__init__.py b/glances/plugins/quicklook/__init__.py index fa68d50c..8646298d 100644 --- a/glances/plugins/quicklook/__init__.py +++ b/glances/plugins/quicklook/__init__.py @@ -9,15 +9,15 @@ """Quicklook plugin.""" -from glances.logger import logger +import psutil + from glances.cpu_percent import cpu_percent -from glances.plugins.load import get_load_average, get_nb_log_core, get_nb_phys_core +from glances.logger import logger from glances.outputs.glances_bars import Bar from glances.outputs.glances_sparklines import Sparkline +from glances.plugins.load import get_load_average, get_nb_log_core, get_nb_phys_core from glances.plugins.plugin.model import GlancesPluginModel -import psutil - # Fields description # description: human readable description # short_name: shortname to use un UI diff --git a/glances/plugins/sensors/__init__.py b/glances/plugins/sensors/__init__.py index 8aed0e94..cb11acde 100644 --- a/glances/plugins/sensors/__init__.py +++ b/glances/plugins/sensors/__init__.py @@ -9,20 +9,20 @@ """Sensors plugin.""" -from enum import Enum +import warnings from concurrent.futures import ThreadPoolExecutor -from typing import List, Dict, Literal, Any +from enum import Enum +from typing import Any, Dict, List, Literal import psutil -import warnings -from glances.logger import logger from glances.globals import to_fahrenheit -from glances.timer import Counter -from glances.plugins.sensors.sensor.glances_batpercent import PluginModel as BatPercentPluginModel -from glances.plugins.sensors.sensor.glances_hddtemp import PluginModel as HddTempPluginModel +from glances.logger import logger from glances.outputs.glances_unicode import unicode_message from glances.plugins.plugin.model import GlancesPluginModel +from glances.plugins.sensors.sensor.glances_batpercent import PluginModel as BatPercentPluginModel +from glances.plugins.sensors.sensor.glances_hddtemp import PluginModel as HddTempPluginModel +from glances.timer import Counter class SensorType(str, Enum): diff --git a/glances/plugins/sensors/sensor/glances_batpercent.py b/glances/plugins/sensors/sensor/glances_batpercent.py index 9baadf5e..8c280c16 100644 --- a/glances/plugins/sensors/sensor/glances_batpercent.py +++ b/glances/plugins/sensors/sensor/glances_batpercent.py @@ -11,9 +11,9 @@ import psutil +from glances.globals import LINUX from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel -from glances.globals import LINUX # Batinfo library (optional; Linux-only) if LINUX: diff --git a/glances/plugins/smart/__init__.py b/glances/plugins/smart/__init__.py index f2e33d32..88f04320 100644 --- a/glances/plugins/smart/__init__.py +++ b/glances/plugins/smart/__init__.py @@ -34,10 +34,10 @@ Check for admin access. If no admin access, disable SMART plugin. If smartmontools is not installed, we should catch the error upstream in plugin initialization. """ -from glances.plugins.plugin.model import GlancesPluginModel +from glances.globals import is_admin from glances.logger import logger from glances.main import disable -from glances.globals import is_admin +from glances.plugins.plugin.model import GlancesPluginModel # Import plugin specific dependency try: diff --git a/glances/plugins/system/__init__.py b/glances/plugins/system/__init__.py index 17e3259a..3cc7a543 100644 --- a/glances/plugins/system/__init__.py +++ b/glances/plugins/system/__init__.py @@ -14,8 +14,8 @@ import platform import re from io import open -from glances.logger import logger from glances.globals import iteritems +from glances.logger import logger from glances.plugins.plugin.model import GlancesPluginModel # { diff --git a/glances/plugins/uptime/__init__.py b/glances/plugins/uptime/__init__.py index 9ded30c5..06283711 100644 --- a/glances/plugins/uptime/__init__.py +++ b/glances/plugins/uptime/__init__.py @@ -11,10 +11,10 @@ from datetime import datetime, timedelta -from glances.plugins.plugin.model import GlancesPluginModel - import psutil +from glances.plugins.plugin.model import GlancesPluginModel + # SNMP OID snmp_oid = {'_uptime': '1.3.6.1.2.1.1.3.0'} diff --git a/glances/plugins/wifi/__init__.py b/glances/plugins/wifi/__init__.py index 843553a6..8f0d26cf 100644 --- a/glances/plugins/wifi/__init__.py +++ b/glances/plugins/wifi/__init__.py @@ -19,9 +19,9 @@ wlp2s0: 0000 51. -59. -256 0 0 0 0 5881 0 import operator -from glances.globals import nativestr, file_exists -from glances.plugins.plugin.model import GlancesPluginModel +from glances.globals import file_exists, nativestr from glances.logger import logger +from glances.plugins.plugin.model import GlancesPluginModel # Backup solution is to use the /proc/net/wireless file # but it only give signal information about the current hotspot diff --git a/glances/ports_list.py b/glances/ports_list.py index ce040230..30f692ab 100644 --- a/glances/ports_list.py +++ b/glances/ports_list.py @@ -9,8 +9,8 @@ """Manage the Glances ports list (Ports plugin).""" -from glances.logger import logger from glances.globals import BSD +from glances.logger import logger # XXX *BSDs: Segmentation fault (core dumped) # -- https://bitbucket.org/al45tair/netifaces/issues/15 diff --git a/glances/processes.py b/glances/processes.py index a3069e0b..c93944a6 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -9,15 +9,14 @@ import os -from glances.globals import BSD, LINUX, MACOS, WINDOWS, iterkeys -from glances.globals import namedtuple_to_dict, list_of_namedtuple_to_list_of_dict -from glances.timer import Timer, getTimeSinceLastUpdate -from glances.filter import GlancesFilterList, GlancesFilter -from glances.programs import processes_to_programs -from glances.logger import logger - import psutil +from glances.filter import GlancesFilter, GlancesFilterList +from glances.globals import BSD, LINUX, MACOS, WINDOWS, iterkeys, list_of_namedtuple_to_list_of_dict, namedtuple_to_dict +from glances.logger import logger +from glances.programs import processes_to_programs +from glances.timer import Timer, getTimeSinceLastUpdate + psutil_version_info = tuple([int(num) for num in psutil.__version__.split('.')]) # This constant defines the list of available processes sort key diff --git a/glances/secure.py b/glances/secure.py index 4dd177e0..30f13803 100644 --- a/glances/secure.py +++ b/glances/secure.py @@ -9,8 +9,8 @@ """Secures functions for Glances""" -from subprocess import Popen, PIPE import re +from subprocess import PIPE, Popen from glances.globals import nativestr diff --git a/glances/server.py b/glances/server.py index ad343e20..55f6139f 100644 --- a/glances/server.py +++ b/glances/server.py @@ -9,14 +9,13 @@ """Manage the Glances server.""" -from glances.globals import json_dumps import socket import sys from base64 import b64decode from glances import __version__ -from glances.globals import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer from glances.autodiscover import GlancesAutoDiscoverClient +from glances.globals import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer, json_dumps from glances.logger import logger from glances.stats_server import GlancesStatsServer from glances.timer import Timer diff --git a/glances/standalone.py b/glances/standalone.py index e717d75e..ae9090c4 100644 --- a/glances/standalone.py +++ b/glances/standalone.py @@ -12,18 +12,17 @@ import sys import time -from glances.logger import logger - from glances.globals import WINDOWS -from glances.processes import glances_processes -from glances.stats import GlancesStats +from glances.logger import logger +from glances.outdated import Outdated from glances.outputs.glances_curses import GlancesCursesStandalone from glances.outputs.glances_stdout import GlancesStdout -from glances.outputs.glances_stdout_json import GlancesStdoutJson +from glances.outputs.glances_stdout_apidoc import GlancesStdoutApiDoc from glances.outputs.glances_stdout_csv import GlancesStdoutCsv from glances.outputs.glances_stdout_issue import GlancesStdoutIssue -from glances.outputs.glances_stdout_apidoc import GlancesStdoutApiDoc -from glances.outdated import Outdated +from glances.outputs.glances_stdout_json import GlancesStdoutJson +from glances.processes import glances_processes +from glances.stats import GlancesStats from glances.timer import Counter diff --git a/glances/stats.py b/glances/stats.py index d65151b3..8722e31e 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -11,14 +11,14 @@ import collections import os +import pathlib import sys import threading import traceback from importlib import import_module -import pathlib -from glances.logger import logger from glances.globals import exports_path, plugins_path, sys_path +from glances.logger import logger from glances.timer import Counter diff --git a/glances/stats_client.py b/glances/stats_client.py index fd27af16..15ad30f3 100644 --- a/glances/stats_client.py +++ b/glances/stats_client.py @@ -11,9 +11,9 @@ import sys -from glances.stats import GlancesStats from glances.globals import sys_path from glances.logger import logger +from glances.stats import GlancesStats class GlancesStatsClient(GlancesStats): diff --git a/glances/stats_client_snmp.py b/glances/stats_client_snmp.py index 9184589c..5007656a 100644 --- a/glances/stats_client_snmp.py +++ b/glances/stats_client_snmp.py @@ -11,9 +11,9 @@ import re -from glances.stats import GlancesStats from glances.globals import iteritems from glances.logger import logger +from glances.stats import GlancesStats # SNMP OID regexp pattern to short system name dict oid_to_short_system_name = { diff --git a/glances/stats_server.py b/glances/stats_server.py index 802f6327..684bbcf6 100644 --- a/glances/stats_server.py +++ b/glances/stats_server.py @@ -11,8 +11,8 @@ import collections -from glances.stats import GlancesStats from glances.logger import logger +from glances.stats import GlancesStats class GlancesStatsServer(GlancesStats): diff --git a/glances/timer.py b/glances/timer.py index 30316b3b..030558cb 100644 --- a/glances/timer.py +++ b/glances/timer.py @@ -9,8 +9,8 @@ """The timer manager.""" -from time import time from datetime import datetime +from time import time # Global list to manage the elapsed time last_update_times = {} diff --git a/glances/webserver.py b/glances/webserver.py index 1451399f..859ce820 100644 --- a/glances/webserver.py +++ b/glances/webserver.py @@ -10,9 +10,9 @@ """Glances Restful/API and Web based interface.""" from glances.globals import WINDOWS +from glances.outputs.glances_restful_api import GlancesRestfulApi from glances.processes import glances_processes from glances.stats import GlancesStats -from glances.outputs.glances_restful_api import GlancesRestfulApi class GlancesWebServer(object): diff --git a/pyproject.toml b/pyproject.toml index 30158d4d..5b6464c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,20 @@ quote-style = "preserve" [tool.ruff.lint] # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. -select = ["E", "F"] +select = [ +# "C90", # mccabe + "E", # pycodestyle + "F", # Pyflakes + "I", # isort +# "N", # pep8-naming + "W", # pycodestyle +# "UP", # pyupgrde +# "C4", # flake8-comprehensions +# "RET", # flake8-return +# "FBT", # flake8-boolean-trap +# "RUF", # Ruff-specific rules +# "PERF", # Perflint +] ignore = [] # Allow autofix for all enabled rules (when `--fix`) is provided. @@ -50,4 +63,4 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. -max-complexity = 10 \ No newline at end of file +max-complexity = 18 \ No newline at end of file diff --git a/run.py b/run.py index a51fb2e1..a5db19e7 100755 --- a/run.py +++ b/run.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- import re import sys + from glances import main if __name__ == '__main__': diff --git a/setup.py b/setup.py index 66a09f5c..2c7ea8d7 100755 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ import re import sys from io import open -from setuptools import setup, Command +from setuptools import Command, setup # Predication warning # Glances version 4 will only be compatible with Python 3.7 and above diff --git a/unittest-core.py b/unittest-core.py index cdaa6ea4..9383883c 100755 --- a/unittest-core.py +++ b/unittest-core.py @@ -10,31 +10,33 @@ """Glances unitary tests suite.""" +import json +import sys import time import unittest -import sys -import json # Check Python version if sys.version_info < (3, 8): print('Glances requires at least Python 3.8 to run.') sys.exit(1) -from glances.main import GlancesMain -from glances.stats import GlancesStats from glances import __version__ -from glances.globals import WINDOWS, LINUX, subsample, string_value_to_float +from glances.events_list import GlancesEventsList +from glances.filter import GlancesFilter, GlancesFilterList +from glances.globals import LINUX, WINDOWS, string_value_to_float, subsample +from glances.main import GlancesMain from glances.outputs.glances_bars import Bar -from glances.thresholds import GlancesThresholdOk -from glances.thresholds import GlancesThresholdCareful -from glances.thresholds import GlancesThresholdWarning -from glances.thresholds import GlancesThresholdCritical -from glances.thresholds import GlancesThresholds from glances.plugins.plugin.model import GlancesPluginModel from glances.programs import processes_to_programs from glances.secure import secure_popen -from glances.events_list import GlancesEventsList -from glances.filter import GlancesFilterList, GlancesFilter +from glances.stats import GlancesStats +from glances.thresholds import ( + GlancesThresholdCareful, + GlancesThresholdCritical, + GlancesThresholdOk, + GlancesThresholds, + GlancesThresholdWarning, +) # Global variables # ================= diff --git a/unittest-restful.py b/unittest-restful.py index ce88c582..72e99b2e 100755 --- a/unittest-restful.py +++ b/unittest-restful.py @@ -10,18 +10,18 @@ """Glances unitary tests suite for the RESTful API.""" +import numbers import os import shlex import subprocess import time -import numbers import unittest -from glances.outputs.glances_restful_api import GlancesRestfulApi +import requests + from glances import __version__ from glances.globals import text_type - -import requests +from glances.outputs.glances_restful_api import GlancesRestfulApi SERVER_PORT = 61234 API_VERSION = GlancesRestfulApi.API_VERSION diff --git a/unittest-xmlrpc.py b/unittest-xmlrpc.py index 03df2bac..c8b10fb9 100755 --- a/unittest-xmlrpc.py +++ b/unittest-xmlrpc.py @@ -10,8 +10,8 @@ """Glances unitary tests suite for the XML-RPC API.""" -import os import json +import os import shlex import subprocess import time From b4c2a4c24ade50d6bc4b46a2054bc7679636360f Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 02:31:54 +0530 Subject: [PATCH 04/14] chg: ruff - flake-return fixes --- glances/amps/amp.py | 12 ++-- glances/attribute.py | 3 +- glances/autodiscover.py | 3 +- glances/client.py | 10 +-- glances/client_browser.py | 3 +- glances/cpu_percent.py | 3 +- glances/events_list.py | 3 +- glances/exports/export.py | 3 +- glances/exports/glances_graphite/__init__.py | 4 +- glances/exports/glances_influxdb2/__init__.py | 3 +- glances/exports/glances_rabbitmq/__init__.py | 7 +- glances/exports/glances_riemann/__init__.py | 17 +++-- glances/exports/glances_statsd/__init__.py | 4 +- glances/filter.py | 6 +- glances/folder_list.py | 3 +- glances/globals.py | 8 +-- glances/outputs/glances_bars.py | 1 + glances/outputs/glances_curses.py | 40 ++++++----- glances/outputs/glances_sparklines.py | 1 + glances/outputs/glances_stdout_apidoc.py | 3 +- glances/outputs/glances_unicode.py | 3 +- glances/password.py | 7 +- glances/password_list.py | 12 ++-- glances/plugins/alert/__init__.py | 3 +- glances/plugins/amps/__init__.py | 12 ++-- glances/plugins/containers/__init__.py | 13 ++-- glances/plugins/containers/engines/docker.py | 3 +- glances/plugins/fs/__init__.py | 6 +- glances/plugins/gpu/cards/amd.py | 12 ++-- glances/plugins/load/__init__.py | 6 +- glances/plugins/plugin/model.py | 71 ++++++++----------- glances/plugins/ports/__init__.py | 3 +- glances/plugins/processlist/__init__.py | 9 ++- glances/plugins/raid/__init__.py | 2 +- glances/plugins/sensors/__init__.py | 12 ++-- glances/plugins/uptime/__init__.py | 4 +- glances/processes.py | 3 +- glances/secure.py | 2 +- glances/server.py | 8 +-- glances/stats.py | 24 +++---- glances/thresholds.py | 13 ++-- pyproject.toml | 2 +- setup.py | 4 +- 43 files changed, 154 insertions(+), 217 deletions(-) diff --git a/glances/amps/amp.py b/glances/amps/amp.py index b34063af..61a3b0a4 100644 --- a/glances/amps/amp.py +++ b/glances/amps/amp.py @@ -109,16 +109,14 @@ class GlancesAmp(object): """Generic method to get the item in the AMP configuration""" if key in self.configs: return self.configs[key] - else: - return None + return None def enable(self): """Return True|False if the AMP is enabled in the configuration file (enable=true|false).""" ret = self.get('enable') if ret is None: return False - else: - return ret.lower().startswith('true') + return ret.lower().startswith('true') def regex(self): """Return regular expression used to identified the current application.""" @@ -133,8 +131,7 @@ class GlancesAmp(object): ret = self.get('one_line') if ret is None: return False - else: - return ret.lower().startswith('true') + return ret.lower().startswith('true') def time_until_refresh(self): """Return time in seconds until refresh.""" @@ -193,5 +190,4 @@ class GlancesAmp(object): # Call the children update method if self.should_update(): return self.update(process_list) - else: - return self.result() + return self.result() diff --git a/glances/attribute.py b/glances/attribute.py index 4c6c7767..22f25ef2 100644 --- a/glances/attribute.py +++ b/glances/attribute.py @@ -66,8 +66,7 @@ class GlancesAttribute(object): def value(self): if self.history_len() > 0: return (self._value[1] - self.history_value()[1]) / (self._value[0] - self.history_value()[0]) - else: - return None + return None @value.setter def value(self, new_value): diff --git a/glances/autodiscover.py b/glances/autodiscover.py index 336af140..9b784697 100644 --- a/glances/autodiscover.py +++ b/glances/autodiscover.py @@ -148,8 +148,7 @@ class GlancesAutoDiscoverServer(object): """Return the current server list (dict of dict).""" if zeroconf_tag and self.zeroconf_enable_tag: return self.listener.get_servers_list() - else: - return [] + return [] def set_server(self, server_pos, key, value): """Set the key to the value for the server_pos (position in the list).""" diff --git a/glances/client.py b/glances/client.py index 1412d1e1..c4cfe185 100644 --- a/glances/client.py +++ b/glances/client.py @@ -182,12 +182,12 @@ class GlancesClient(object): """Update stats from Glances/SNMP server.""" if self.client_mode == 'glances': return self.update_glances() - elif self.client_mode == 'snmp': + if self.client_mode == 'snmp': return self.update_snmp() - else: - self.end() - logger.critical("Unknown server mode: {}".format(self.client_mode)) - sys.exit(2) + + self.end() + logger.critical("Unknown server mode: {}".format(self.client_mode)) + sys.exit(2) def update_glances(self): """Get stats from Glances server. diff --git a/glances/client_browser.py b/glances/client_browser.py index c8ba9a8a..1409d316 100644 --- a/glances/client_browser.py +++ b/glances/client_browser.py @@ -77,8 +77,7 @@ class GlancesClientBrowser(object): if clear_password is not None: server['password'] = self.password.get_hash(clear_password) return 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port']) - else: - return 'http://{}:{}'.format(server['ip'], server['port']) + return 'http://{}:{}'.format(server['ip'], server['port']) def __update_stats(self, server): """Update stats for the given server (picked from the server list)""" diff --git a/glances/cpu_percent.py b/glances/cpu_percent.py index f978f863..e6fe96ec 100644 --- a/glances/cpu_percent.py +++ b/glances/cpu_percent.py @@ -46,8 +46,7 @@ class CpuPercent(object): If percpu, return the percpu stats""" if percpu: return self.__get_percpu() - else: - return self.__get_cpu() + return self.__get_cpu() def get_info(self): """Get additional information about the CPU""" diff --git a/glances/events_list.py b/glances/events_list.py index b50ec83f..e1105d5f 100644 --- a/glances/events_list.py +++ b/glances/events_list.py @@ -158,8 +158,7 @@ def build_global_message(): if themax['weight'] >= themax['thresholds_min']: # Check if the weight is > to the minimal threshold value return themax['msg'] - else: - return tree[0]['msg'] + return tree[0]['msg'] class GlancesEventsList(object): diff --git a/glances/exports/export.py b/glances/exports/export.py index 4b57a122..b92654ea 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -122,8 +122,7 @@ class GlancesExport(object): logger.error("No 'key' available in {}".format(item)) if isinstance(ret, list): return ret[0] - else: - return ret + return ret def parse_tags(self, tags): """Parse tags into a dict. diff --git a/glances/exports/glances_graphite/__init__.py b/glances/exports/glances_graphite/__init__.py index 84289238..2defe864 100644 --- a/glances/exports/glances_graphite/__init__.py +++ b/glances/exports/glances_graphite/__init__.py @@ -100,6 +100,4 @@ def normalize(name): """Normalize name for the Graphite convention""" # Name should not contain space - ret = name.replace(' ', '_') - - return ret + return name.replace(' ', '_') diff --git a/glances/exports/glances_influxdb2/__init__.py b/glances/exports/glances_influxdb2/__init__.py index 8b8ea964..7e10b8b3 100644 --- a/glances/exports/glances_influxdb2/__init__.py +++ b/glances/exports/glances_influxdb2/__init__.py @@ -84,7 +84,7 @@ class Export(GlancesExport): ) # Create the write client - write_client = client.write_api( + return client.write_api( write_options=WriteOptions( batch_size=500, flush_interval=self.interval * 1000, @@ -95,7 +95,6 @@ class Export(GlancesExport): exponential_base=2, ) ) - return write_client def _normalize(self, name, columns, points): """Normalize data for the InfluxDB's data model. diff --git a/glances/exports/glances_rabbitmq/__init__.py b/glances/exports/glances_rabbitmq/__init__.py index 0cec274e..5d481aa1 100644 --- a/glances/exports/glances_rabbitmq/__init__.py +++ b/glances/exports/glances_rabbitmq/__init__.py @@ -67,8 +67,7 @@ class Export(GlancesExport): self.protocol + '://' + self.user + ':' + self.password + '@' + self.host + ':' + self.port + '/' ) connection = pika.BlockingConnection(parameters) - channel = connection.channel() - return channel + return connection.channel() except Exception as e: logger.critical("Connection to rabbitMQ server %s:%s failed. %s" % (self.host, self.port, e)) sys.exit(2) @@ -79,8 +78,8 @@ class Export(GlancesExport): for i in range(len(columns)): if not isinstance(points[i], Number): continue - else: - data += ", " + columns[i] + "=" + str(points[i]) + data += ", " + columns[i] + "=" + str(points[i]) + logger.debug(data) try: self.client.basic_publish(exchange='', routing_key=self.queue, body=data) diff --git a/glances/exports/glances_riemann/__init__.py b/glances/exports/glances_riemann/__init__.py index 79dd2cb8..50e12e05 100644 --- a/glances/exports/glances_riemann/__init__.py +++ b/glances/exports/glances_riemann/__init__.py @@ -48,8 +48,7 @@ class Export(GlancesExport): if not self.export_enable: return None try: - client = bernhard.Client(host=self.host, port=self.port) - return client + return bernhard.Client(host=self.host, port=self.port) except Exception as e: logger.critical("Connection to Riemann failed : %s " % e) return None @@ -59,10 +58,10 @@ class Export(GlancesExport): for i in range(len(columns)): if not isinstance(points[i], Number): continue - else: - data = {'host': self.hostname, 'service': name + " " + columns[i], 'metric': points[i]} - logger.debug(data) - try: - self.client.send(data) - except Exception as e: - logger.error("Cannot export stats to Riemann (%s)" % e) + + data = {'host': self.hostname, 'service': name + " " + columns[i], 'metric': points[i]} + logger.debug(data) + try: + self.client.send(data) + except Exception as e: + logger.error("Cannot export stats to Riemann (%s)" % e) diff --git a/glances/exports/glances_statsd/__init__.py b/glances/exports/glances_statsd/__init__.py index d65c36ca..89dd3f33 100644 --- a/glances/exports/glances_statsd/__init__.py +++ b/glances/exports/glances_statsd/__init__.py @@ -69,6 +69,4 @@ def normalize(name): # Name should not contain some specials chars (issue #1068) ret = name.replace(':', '') ret = ret.replace('%', '') - ret = ret.replace(' ', '_') - - return ret + return ret.replace(' ', '_') diff --git a/glances/filter.py b/glances/filter.py index c0a4a529..e2061277 100644 --- a/glances/filter.py +++ b/glances/filter.py @@ -156,9 +156,9 @@ class GlancesFilter(object): if self.filter_key is None: # Apply filter on command line and process name return self._is_process_filtered(process, key='name') or self._is_process_filtered(process, key='cmdline') - else: - # Apply filter on - return self._is_process_filtered(process) + + # Apply filter on + return self._is_process_filtered(process) def _is_process_filtered(self, process, key=None): """Return True if the process[key] should be filtered according to the current filter""" diff --git a/glances/folder_list.py b/glances/folder_list.py index 5820e847..2211e5f6 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -67,8 +67,7 @@ class FolderList(object): value['path'] = self.config.get_value(section, key + 'path') if value['path'] is None: continue - else: - value['path'] = nativestr(value['path']) + value['path'] = nativestr(value['path']) # Optional conf keys # Refresh time diff --git a/glances/globals.py b/glances/globals.py index e18a9f35..43c3b697 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -128,10 +128,9 @@ def b(s, errors='replace'): def nativestr(s, errors='replace'): if isinstance(s, text_type): return s - elif isinstance(s, (int, float)): + if isinstance(s, (int, float)): return s.__str__() - else: - return s.decode('utf-8', errors=errors) + return s.decode('utf-8', errors=errors) def system_exec(command): @@ -331,8 +330,7 @@ def json_dumps_dictlist(data, item): dl = dictlist(data, item) if dl is None: return None - else: - return json_dumps(dl) + return json_dumps(dl) def string_value_to_float(s): diff --git a/glances/outputs/glances_bars.py b/glances/outputs/glances_bars.py index d434c0f9..d6012b9a 100644 --- a/glances/outputs/glances_bars.py +++ b/glances/outputs/glances_bars.py @@ -76,6 +76,7 @@ class Bar(object): return self.__size if self.__display_value: return self.__size - 6 + return None @property def percent(self): diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index bed7970a..5a8321af 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -154,9 +154,9 @@ class _GlancesCurses(object): logger.info("Cannot init the curses library, quiet mode on and export.") args.quiet = True return - else: - logger.critical("Cannot init the curses library ({})".format(e)) - sys.exit(1) + + logger.critical("Cannot init the curses library ({})".format(e)) + sys.exit(1) # Load configuration file self.load_config(config) @@ -359,8 +359,7 @@ class _GlancesCurses(object): def get_key(self, window): # TODO: Check issue #163 - ret = window.getch() - return ret + return window.getch() def __catch_key(self, return_to_browser=False): # Catch the pressed key @@ -990,7 +989,8 @@ class _GlancesCurses(object): popup.refresh() self.wait(duration * 1000) return True - elif popup_type == 'input': + + if popup_type == 'input': logger.info(popup_type) logger.info(is_password) # Create a sub-window for the text field @@ -1010,17 +1010,17 @@ class _GlancesCurses(object): self.set_cursor(0) if textbox != '': return textbox - else: - return None - else: - textbox = GlancesTextbox(sub_pop, insert_mode=True) - textbox.edit() - self.set_cursor(0) - if textbox.gather() != '': - return textbox.gather()[:-1] - else: - return None - elif popup_type == 'yesno': + return None + + # No password + textbox = GlancesTextbox(sub_pop, insert_mode=True) + textbox.edit() + self.set_cursor(0) + if textbox.gather() != '': + return textbox.gather()[:-1] + return None + + if popup_type == 'yesno': # # Create a sub-window for the text field sub_pop = popup.derwin(1, 2, len(sentence_list) + 1, len(m) + 2) sub_pop.attron(self.colors_list['FILTER']) @@ -1038,6 +1038,8 @@ class _GlancesCurses(object): # self.term_window.keypad(0) return textbox.gather() + return None + def display_plugin(self, plugin_stats, display_optional=True, display_additional=True, max_y=65535, add_space=0): """Display the plugin_stats on the screen. @@ -1132,6 +1134,7 @@ class _GlancesCurses(object): # Have empty lines after the plugins self.next_line += add_space + return None def clear(self): """Erase the content of the screen. @@ -1214,8 +1217,7 @@ class _GlancesCurses(object): if isexitkey and self.args.help_tag: # Quit from help should return to main screen, not exit #1874 self.args.help_tag = not self.args.help_tag - isexitkey = False - return isexitkey + return False if not isexitkey and pressedkey > -1: # Redraw display diff --git a/glances/outputs/glances_sparklines.py b/glances/outputs/glances_sparklines.py index d4ada88c..99f6e9fe 100644 --- a/glances/outputs/glances_sparklines.py +++ b/glances/outputs/glances_sparklines.py @@ -59,6 +59,7 @@ class Sparkline(object): return self.__size if self.__display_value: return self.__size - 6 + return None @property def percents(self): diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 907d4929..8b9350d9 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -82,8 +82,7 @@ def indent_stat(stat, indent=' '): if isinstance(stat, list) and len(stat) > 1 and isinstance(stat[0], dict): # Only display two first items return indent + pformat(stat[0:2]).replace('\n', '\n' + indent).replace("'", '"') - else: - return indent + pformat(stat).replace('\n', '\n' + indent).replace("'", '"') + return indent + pformat(stat).replace('\n', '\n' + indent).replace("'", '"') def print_api_status(): diff --git a/glances/outputs/glances_unicode.py b/glances/outputs/glances_unicode.py index 76ae3e60..99f4e786 100644 --- a/glances/outputs/glances_unicode.py +++ b/glances/outputs/glances_unicode.py @@ -25,5 +25,4 @@ def unicode_message(key, args=None): """Return the unicode message for the given key.""" if args and hasattr(args, 'disable_unicode') and args.disable_unicode: return _unicode_message[key][1] - else: - return _unicode_message[key][0] + return _unicode_message[key][0] diff --git a/glances/password.py b/glances/password.py index c4e8280e..9d79e995 100644 --- a/glances/password.py +++ b/glances/password.py @@ -38,8 +38,7 @@ class GlancesPassword(object): """ if self.config is None: return user_config_dir()[0] - else: - return self.config.get_value('passwords', 'local_password_path', default=user_config_dir()[0]) + return self.config.get_value('passwords', 'local_password_path', default=user_config_dir()[0]) @weak_lru_cache(maxsize=32) def get_hash(self, plain_password, salt=''): @@ -120,6 +119,4 @@ class GlancesPassword(object): """Load the hashed password from the Glances folder.""" # Read the password file, if it exists with open(self.password_file, 'r') as file_pwd: - hashed_password = file_pwd.read() - - return hashed_password + return file_pwd.read() diff --git a/glances/password_list.py b/glances/password_list.py index 21ee3c7a..1f3973fa 100644 --- a/glances/password_list.py +++ b/glances/password_list.py @@ -51,14 +51,14 @@ class GlancesPasswordList(GlancesPassword): """ if host is None: return self._password_dict - else: + + try: + return self._password_dict[host] + except (KeyError, TypeError): try: - return self._password_dict[host] + return self._password_dict['default'] except (KeyError, TypeError): - try: - return self._password_dict['default'] - except (KeyError, TypeError): - return None + return None def set_password(self, host, password): """Set a password for a specific host.""" diff --git a/glances/plugins/alert/__init__.py b/glances/plugins/alert/__init__.py index 8275bb30..4068d395 100644 --- a/glances/plugins/alert/__init__.py +++ b/glances/plugins/alert/__init__.py @@ -183,5 +183,4 @@ class PluginModel(GlancesPluginModel): """Compare a with b using the tolerance (if numerical).""" if str(int(a)).isdigit() and str(int(b)).isdigit(): return abs(a - b) <= max(abs(a), abs(b)) * tolerance - else: - return a == b + return a == b diff --git a/glances/plugins/amps/__init__.py b/glances/plugins/amps/__init__.py index 9e9e46be..acdcf315 100644 --- a/glances/plugins/amps/__init__.py +++ b/glances/plugins/amps/__init__.py @@ -93,13 +93,11 @@ class PluginModel(GlancesPluginModel): if nbprocess > 0: if int(countmin) <= int(nbprocess) <= int(countmax): return 'OK' - else: - return 'WARNING' - else: - if int(countmin) == 0: - return 'OK' - else: - return 'CRITICAL' + return 'WARNING' + + if int(countmin) == 0: + return 'OK' + return 'CRITICAL' def msg_curse(self, args=None, max_width=None): """Return the dict to display in the curse interface.""" diff --git a/glances/plugins/containers/__init__.py b/glances/plugins/containers/__init__.py index e88d1d36..024b97fa 100644 --- a/glances/plugins/containers/__init__.py +++ b/glances/plugins/containers/__init__.py @@ -164,8 +164,7 @@ class PluginModel(GlancesPluginModel): conf_podman_sock = self.get_conf_value('podman_sock') if len(conf_podman_sock) == 0: return "unix:///run/user/1000/podman/podman.sock" - else: - return conf_podman_sock[0] + return conf_podman_sock[0] def exit(self): """Overwrite the exit method to close threads.""" @@ -209,8 +208,7 @@ class PluginModel(GlancesPluginModel): all_tag = self.get_conf_value('all') if len(all_tag) == 0: return False - else: - return all_tag[0].lower() == 'true' + return all_tag[0].lower() == 'true' @GlancesPluginModel._check_decorator @GlancesPluginModel._log_result_decorator @@ -453,12 +451,11 @@ class PluginModel(GlancesPluginModel): """Analyse the container status.""" if status == 'running': return 'OK' - elif status == 'exited': + if status == 'exited': return 'WARNING' - elif status == 'dead': + if status == 'dead': return 'CRITICAL' - else: - return 'CAREFUL' + return 'CAREFUL' def sort_docker_stats(stats): diff --git a/glances/plugins/containers/engines/docker.py b/glances/plugins/containers/engines/docker.py index a74e2a70..ab27dadc 100644 --- a/glances/plugins/containers/engines/docker.py +++ b/glances/plugins/containers/engines/docker.py @@ -71,13 +71,12 @@ class DockerStatsFetcher: memory_stats = self._get_memory_stats() network_stats = self._get_network_stats() - computed_stats = { + return { "io": io_stats or {}, "memory": memory_stats or {}, "network": network_stats or {}, "cpu": cpu_stats or {"total": 0.0}, } - return computed_stats @property def time_since_update(self): diff --git a/glances/plugins/fs/__init__.py b/glances/plugins/fs/__init__.py index d5affe5b..49bb4f29 100644 --- a/glances/plugins/fs/__init__.py +++ b/glances/plugins/fs/__init__.py @@ -216,8 +216,7 @@ class PluginModel(GlancesPluginModel): # Do not take hidden file system into account if self.is_hide(fs_current['mnt_point']): continue - else: - stats.append(fs_current) + stats.append(fs_current) else: # Default behavior for fs in fs_stat: @@ -232,8 +231,7 @@ class PluginModel(GlancesPluginModel): # Do not take hidden file system into account if self.is_hide(fs_current['mnt_point']) or self.is_hide(fs_current['device_name']): continue - else: - stats.append(fs_current) + stats.append(fs_current) # Update the stats self.stats = stats diff --git a/glances/plugins/gpu/cards/amd.py b/glances/plugins/gpu/cards/amd.py index 2f8cd562..2223fae4 100644 --- a/glances/plugins/gpu/cards/amd.py +++ b/glances/plugins/gpu/cards/amd.py @@ -37,6 +37,7 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually import os import re +from typing import Optional DRM_ROOT_FOLDER: str = '/sys/class/drm' CARD_REGEX: str = r"^card\d$" @@ -104,7 +105,7 @@ def get_device_name(device_folder: str) -> str: return 'AMD GPU' -def get_mem(device_folder: str) -> int: +def get_mem(device_folder: str) -> Optional[int]: """Return the memory consumption in %.""" mem_info_vram_total = os.path.join(device_folder, GPU_MEM_TOTAL) mem_info_vram_used = os.path.join(device_folder, GPU_MEM_USED) @@ -118,7 +119,7 @@ def get_mem(device_folder: str) -> int: return None -def get_proc(device_folder: str) -> int: +def get_proc(device_folder: str) -> Optional[int]: """Return the processor consumption in %.""" gpu_busy_percent = os.path.join(device_folder, GPU_PROC_PERCENT) if os.path.isfile(gpu_busy_percent): @@ -127,7 +128,7 @@ def get_proc(device_folder: str) -> int: return None -def get_temperature(device_folder: str) -> int: +def get_temperature(device_folder: str) -> Optional[int]: """Return the processor temperature in °C (mean of all HWMON)""" temp_input = [] for root, dirs, _ in os.walk(device_folder): @@ -140,10 +141,9 @@ def get_temperature(device_folder: str) -> int: temp_input.append(int(f.read())) if len(temp_input) > 0: return round(sum(temp_input) / len(temp_input) / 1000) - else: - return None + return None -def get_fan_speed(device_folder: str) -> int: +def get_fan_speed(device_folder: str) -> Optional[int]: """Return the fan speed in %.""" return None diff --git a/glances/plugins/load/__init__.py b/glances/plugins/load/__init__.py index c26446bc..9c3c81bc 100644 --- a/glances/plugins/load/__init__.py +++ b/glances/plugins/load/__init__.py @@ -111,8 +111,7 @@ class PluginModel(GlancesPluginModel): stats = self.get_stats_snmp(snmp_oid=snmp_oid) if stats['min1'] == '': - stats = self.get_init_value() - return stats + return self.get_init_value() # Python 3 return a dict like: # {'min1': "b'0.08'", 'min5': "b'0.12'", 'min15': "b'0.15'"} @@ -206,5 +205,4 @@ def get_load_average(percent: bool = False): if load_average and percent: return tuple([round(i / get_nb_log_core() * 100, 1) for i in load_average]) - else: - return load_average + return load_average diff --git a/glances/plugins/plugin/model.py b/glances/plugins/plugin/model.py index 42973918..9e40fce1 100644 --- a/glances/plugins/plugin/model.py +++ b/glances/plugins/plugin/model.py @@ -151,7 +151,7 @@ class GlancesPluginModel(object): def get_key(self): """Return the key of the list.""" - return None + return def is_enabled(self, plugin_name=None): """Return true if plugin is enabled.""" @@ -227,11 +227,9 @@ class GlancesPluginModel(object): s = self.stats_history.get(nb=nb) if item is None: return s - else: - if item in s: - return s[item] - else: - return None + if item in s: + return s[item] + return None def get_export_history(self, item=None): """Return the stats history object to export.""" @@ -410,14 +408,14 @@ class GlancesPluginModel(object): """ if not isinstance(self.get_raw(), list): return None - else: - if (not isinstance(value, int) and not isinstance(value, float)) and value.isdigit(): - value = int(value) - try: - return {value: [i for i in self.get_raw() if i[item] == value]} - except (KeyError, ValueError) as e: - logger.error("Cannot get item({})=value({}) ({})".format(item, value, e)) - return None + + if (not isinstance(value, int) and not isinstance(value, float)) and value.isdigit(): + value = int(value) + try: + return {value: [i for i in self.get_raw() if i[item] == value]} + except (KeyError, ValueError) as e: + logger.error("Cannot get item({})=value({}) ({})".format(item, value, e)) + return None def get_stats_value(self, item, value): """Return the stats object for a specific item=value in JSON format. @@ -427,15 +425,13 @@ class GlancesPluginModel(object): rsv = self.get_raw_stats_value(item, value) if rsv is None: return None - else: - return json_dumps(rsv) + return json_dumps(rsv) def get_item_info(self, item, key, default=None): """Return the item info grabbed into self.fields_description.""" if self.fields_description is None or item not in self.fields_description: return default - else: - return self.fields_description[item].get(key, default) + return self.fields_description[item].get(key, default) def update_views_hidden(self): """Update the hidden views @@ -553,14 +549,11 @@ class GlancesPluginModel(object): if key is None: return item_views - else: - if option is None: - return item_views[key] - else: - if option in item_views[key]: - return item_views[key][option] - else: - return 'DEFAULT' + if option is None: + return item_views[key] + if option in item_views[key]: + return item_views[key][option] + return 'DEFAULT' def get_json_views(self, item=None, key=None, option=None): """Return the views (in JSON).""" @@ -626,8 +619,7 @@ class GlancesPluginModel(object): """Return the limits object.""" if item is None: return self._limits - else: - return self._limits.get('{}_{}'.format(self.plugin_name, item), None) + return self._limits.get('{}_{}'.format(self.plugin_name, item), None) def get_stats_action(self): """Return stats for the action. @@ -742,12 +734,11 @@ class GlancesPluginModel(object): """Filter the stats to keep only the fields we want (the one defined in fields_description).""" if hasattr(stats, '_asdict'): return {k: v for k, v in stats._asdict().items() if k in self.fields_description} - elif isinstance(stats, dict): + if isinstance(stats, dict): return {k: v for k, v in stats.items() if k in self.fields_description} - elif isinstance(stats, list): + if isinstance(stats, list): return [self.filter_stats(s) for s in stats] - else: - return stats + return stats def manage_threshold(self, stat_name, trigger): """Manage the threshold for the current stat.""" @@ -793,8 +784,7 @@ class GlancesPluginModel(object): """Return true if the criticality limit exist for the given stat_name""" if stat_name == "": return self.plugin_name + '_' + criticality in self._limits - else: - return stat_name + '_' + criticality in self._limits + return stat_name + '_' + criticality in self._limits def get_limit(self, criticality=None, stat_name=""): """Return the limit value for the given criticality. @@ -806,7 +796,7 @@ class GlancesPluginModel(object): # Example: network_wlan0_rx_careful if stat_name + '_' + criticality in self._limits: return self._limits[stat_name + '_' + criticality] - elif self.plugin_name + '_' + criticality in self._limits: + if self.plugin_name + '_' + criticality in self._limits: return self._limits[self.plugin_name + '_' + criticality] # No key found, the raise an error @@ -840,10 +830,9 @@ class GlancesPluginModel(object): # Example: network_wlan0_rx_log if stat_name + '_log' in self._limits: return self._limits[stat_name + '_log'][0].lower() == 'true' - elif self.plugin_name + '_log' in self._limits: + if self.plugin_name + '_log' in self._limits: return self._limits[self.plugin_name + '_log'][0].lower() == 'true' - else: - return default_action + return default_action def get_conf_value(self, value, header="", plugin_name=None, default=[]): """Return the configuration (header_) value for the current plugin. @@ -895,14 +884,12 @@ class GlancesPluginModel(object): """Return True if the value should be displayed in the UI""" if self.get_conf_value('show', header=header) != []: return self.is_show(value, header=header) - else: - return not self.is_hide(value, header=header) + return not self.is_hide(value, header=header) def read_alias(self): if self.plugin_name + '_' + 'alias' in self._limits: return {i.split(':')[0].lower(): i.split(':')[1] for i in self._limits[self.plugin_name + '_' + 'alias']} - else: - return dict() + return dict() def has_alias(self, header): """Return the alias name for the relative header it it exists otherwise None.""" diff --git a/glances/plugins/ports/__init__.py b/glances/plugins/ports/__init__.py index 87c467fc..78e58347 100644 --- a/glances/plugins/ports/__init__.py +++ b/glances/plugins/ports/__init__.py @@ -313,8 +313,7 @@ class ThreadScanner(threading.Thread): """Scan the port structure (dict) and update the status key.""" if int(port['port']) == 0: return self._port_scan_icmp(port) - else: - return self._port_scan_tcp(port) + return self._port_scan_tcp(port) def _resolv_name(self, hostname): """Convert hostname to IP address.""" diff --git a/glances/plugins/processlist/__init__.py b/glances/plugins/processlist/__init__.py index b2a4bf2f..fab3e12b 100644 --- a/glances/plugins/processlist/__init__.py +++ b/glances/plugins/processlist/__init__.py @@ -835,8 +835,7 @@ class PluginModel(GlancesPluginModel): """Return the decoration string for the current mmm status.""" if mmm is not None: return 'DEFAULT' - else: - return 'FILTER' + return 'FILTER' def __mmm_reset(self): """Reset the MMM stats.""" @@ -902,6 +901,6 @@ class PluginModel(GlancesPluginModel): """Return the maximum PID size in number of char.""" if self.pid_max is not None: return len(str(self.pid_max)) - else: - # By default return 5 (corresponding to 99999 PID number) - return 5 + + # By default return 5 (corresponding to 99999 PID number) + return 5 diff --git a/glances/plugins/raid/__init__.py b/glances/plugins/raid/__init__.py index 2145a169..c9fcdf7f 100644 --- a/glances/plugins/raid/__init__.py +++ b/glances/plugins/raid/__init__.py @@ -161,6 +161,6 @@ class PluginModel(GlancesPluginModel): return 'CRITICAL' if used is None or available is None: return 'DEFAULT' - elif used < available: + if used < available: return 'WARNING' return 'OK' diff --git a/glances/plugins/sensors/__init__.py b/glances/plugins/sensors/__init__.py index cb11acde..4eb1f116 100644 --- a/glances/plugins/sensors/__init__.py +++ b/glances/plugins/sensors/__init__.py @@ -153,8 +153,7 @@ class PluginModel(GlancesPluginModel): # Remove duplicates thanks to https://stackoverflow.com/a/9427216/1919431 stats_transformed = [dict(t) for t in {tuple(d.items()) for d in stats_transformed}] # Sort by label - stats_transformed = sorted(stats_transformed, key=lambda d: d['label']) - return stats_transformed + return sorted(stats_transformed, key=lambda d: d['label']) @GlancesPluginModel._check_decorator @GlancesPluginModel._log_result_decorator @@ -191,10 +190,9 @@ class PluginModel(GlancesPluginModel): # Get the alias for each stat if self.has_alias(stats["label"].lower()): return self.has_alias(stats["label"].lower()) - elif self.has_alias("{}_{}".format(stats["label"], stats["type"]).lower()): + if self.has_alias("{}_{}".format(stats["label"], stats["type"]).lower()): return self.has_alias("{}_{}".format(stats["label"], stats["type"]).lower()) - else: - return stats["label"] + return stats["label"] def __set_type(self, stats, sensor_type): """Set the plugin type. @@ -254,9 +252,9 @@ class PluginModel(GlancesPluginModel): return '' if stats['status'].startswith('Charg'): return unicode_message('ARROW_UP') - elif stats['status'].startswith('Discharg'): + if stats['status'].startswith('Discharg'): return unicode_message('ARROW_DOWN') - elif stats['status'].startswith('Full'): + if stats['status'].startswith('Full'): return unicode_message('CHECK') return '' diff --git a/glances/plugins/uptime/__init__.py b/glances/plugins/uptime/__init__.py index 06283711..0e3f71eb 100644 --- a/glances/plugins/uptime/__init__.py +++ b/glances/plugins/uptime/__init__.py @@ -83,6 +83,4 @@ class PluginModel(GlancesPluginModel): if not self.stats or self.is_disabled(): return ret - ret = [self.curse_add_line('Uptime: {}'.format(self.stats))] - - return ret + return [self.curse_add_line('Uptime: {}'.format(self.stats))] diff --git a/glances/processes.py b/glances/processes.py index c93944a6..fea4c004 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -568,8 +568,7 @@ class GlancesProcesses(object): If as_programs is True, return the list of programs.""" if as_programs: return processes_to_programs(self.processlist) - else: - return self.processlist + return self.processlist def get_export(self): """Return the processlist for export.""" diff --git a/glances/secure.py b/glances/secure.py index 30f13803..03745d3a 100644 --- a/glances/secure.py +++ b/glances/secure.py @@ -40,7 +40,7 @@ def __secure_popen(cmd): cmd_split_redirect = cmd.split('>') if len(cmd_split_redirect) > 2: return 'Glances error: Only one file redirection allowed ({})'.format(cmd) - elif len(cmd_split_redirect) == 2: + if len(cmd_split_redirect) == 2: stdout_redirect = cmd_split_redirect[1].strip() cmd = cmd_split_redirect[0] else: diff --git a/glances/server.py b/glances/server.py index 55f6139f..55b48831 100644 --- a/glances/server.py +++ b/glances/server.py @@ -68,17 +68,15 @@ class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, object): # TODO: config is not taken into account: it may be a problem ? pwd = GlancesPassword(username=username, config=None) return pwd.check_password(self.server.user_dict[username], password) - else: - return False + return False def parse_request(self): if SimpleXMLRPCRequestHandler.parse_request(self): # Next we authenticate if self.authenticate(self.headers): return True - else: - # if authentication fails, tell the client - self.send_error(401, 'Authentication failed') + # if authentication fails, tell the client + self.send_error(401, 'Authentication failed') return False def log_message(self, log_format, *args): diff --git a/glances/stats.py b/glances/stats.py index 8722e31e..0f55990f 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -55,10 +55,9 @@ class GlancesStats(object): if hasattr(plugin, 'get_json_views'): # The method get_views exist, return it return getattr(plugin, 'get_json_views') - else: - # The method get_views is not found for the plugin - raise AttributeError(item) - elif item.startswith('get'): + # The method get_views is not found for the plugin + raise AttributeError(item) + if item.startswith('get'): # Get the plugin name plugname = item[len('get') :].lower() # Get the plugin instance @@ -66,12 +65,10 @@ class GlancesStats(object): if hasattr(plugin, 'get_stats'): # The method get_stats exist, return it return getattr(plugin, 'get_stats') - else: - # The method get_stats is not found for the plugin - raise AttributeError(item) - else: - # Default behavior + # The method get_stats is not found for the plugin raise AttributeError(item) + # Default behavior + raise AttributeError(item) def load_modules(self, args): """Wrapper to load: plugins and export modules.""" @@ -237,8 +234,7 @@ class GlancesStats(object): """ if enable: return [p for p in self._plugins if self._plugins[p].is_enabled()] - else: - return [p for p in self._plugins] + return [p for p in self._plugins] def getExportsList(self, enable=True): """Return the exports list. @@ -250,8 +246,7 @@ class GlancesStats(object): """ if enable: return [e for e in self._exports] - else: - return [e for e in self._exports_all] + return [e for e in self._exports_all] def load_limits(self, config=None): """Load the stats limits (except the one in the exclude list).""" @@ -367,8 +362,7 @@ class GlancesStats(object): """Return the plugin name.""" if plugin_name in self._plugins: return self._plugins[plugin_name] - else: - return None + return None def end(self): """End of the Glances stats.""" diff --git a/glances/thresholds.py b/glances/thresholds.py index 9c352831..a7624450 100644 --- a/glances/thresholds.py +++ b/glances/thresholds.py @@ -38,18 +38,17 @@ class GlancesThresholds(object): if stat_name in self._thresholds: return self._thresholds[stat_name] - else: - return {} + return {} def add(self, stat_name, threshold_description): """Add a new threshold to the dict (key = stat_name)""" if threshold_description not in self.threshold_list: return False - else: - self._thresholds[stat_name] = getattr( - self.current_module, 'GlancesThreshold' + threshold_description.capitalize() - )() - return True + + self._thresholds[stat_name] = getattr( + self.current_module, 'GlancesThreshold' + threshold_description.capitalize() + )() + return True # Global variable uses to share thresholds between Glances components diff --git a/pyproject.toml b/pyproject.toml index 5b6464c3..61ed8c3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ select = [ "W", # pycodestyle # "UP", # pyupgrde # "C4", # flake8-comprehensions -# "RET", # flake8-return + "RET", # flake8-return # "FBT", # flake8-boolean-trap # "RUF", # Ruff-specific rules # "PERF", # Perflint diff --git a/setup.py b/setup.py index 2c7ea8d7..e220b2f6 100755 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ with open('README.rst', encoding='utf-8') as f: def get_data_files(): - data_files = [ + return [ ( 'share/doc/glances', ['AUTHORS', 'COPYING', 'NEWS.rst', 'README.rst', "SECURITY.md", 'CONTRIBUTING.md', 'conf/glances.conf'], @@ -39,8 +39,6 @@ def get_data_files(): ('share/man/man1', ['docs/man/glances.1']), ] - return data_files - with open('requirements.txt') as f: required = f.read().splitlines() From 1f628642d4e5cb883edb65bc1d810ef2d807f3ff Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 02:58:30 +0530 Subject: [PATCH 05/14] fix: auto-removed imports in globals --- glances/globals.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/glances/globals.py b/glances/globals.py index 43c3b697..c0f393dc 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -1,3 +1,4 @@ +# ruff: noqa: F401 # -*- coding: utf-8 -*- # # This file is part of Glances. @@ -18,14 +19,20 @@ import errno import functools import os import platform +import queue import re import subprocess import sys import weakref +from configparser import ConfigParser, NoOptionError, NoSectionError from datetime import datetime from operator import itemgetter, methodcaller from statistics import mean +from urllib.error import HTTPError, URLError +from urllib.parse import urlparse from urllib.request import Request, urlopen +from xmlrpc.client import Fault, ProtocolError, Server, ServerProxy, Transport +from xmlrpc.server import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer import ujson From f9a06a31f063ce0db66ba54a1d576b4c0ea94466 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 03:03:16 +0530 Subject: [PATCH 06/14] chg: ruff - mccabe (CC>21) --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 61ed8c3e..feb629db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ quote-style = "preserve" [tool.ruff.lint] # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. select = [ -# "C90", # mccabe + "C90", # mccabe "E", # pycodestyle "F", # Pyflakes "I", # isort @@ -63,4 +63,4 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. -max-complexity = 18 \ No newline at end of file +max-complexity = 21 \ No newline at end of file From 108ffcdfb637e288479f49ec083f601a1e88f51c Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 03:05:33 +0530 Subject: [PATCH 07/14] chg: ruff - pyupgrade --- docs/conf.py | 1 - glances/__init__.py | 33 ++-- glances/__main__.py | 1 - glances/actions.py | 9 +- glances/amps/amp.py | 18 +-- glances/amps/default/__init__.py | 5 +- glances/amps/nginx/__init__.py | 1 - glances/amps/systemd/__init__.py | 5 +- glances/amps/systemv/__init__.py | 5 +- glances/amps_list.py | 13 +- glances/attribute.py | 3 +- glances/autodiscover.py | 43 +++-- glances/client.py | 37 ++--- glances/client_browser.py | 22 ++- glances/config.py | 13 +- glances/cpu_percent.py | 7 +- glances/event.py | 1 - glances/events_list.py | 3 +- glances/exports/export.py | 25 ++- glances/exports/glances_cassandra/__init__.py | 34 ++-- glances/exports/glances_couchdb/__init__.py | 17 +- glances/exports/glances_csv/__init__.py | 19 ++- .../exports/glances_elasticsearch/__init__.py | 23 ++- glances/exports/glances_graph/__init__.py | 15 +- glances/exports/glances_graphite/__init__.py | 13 +- glances/exports/glances_influxdb/__init__.py | 19 +-- glances/exports/glances_influxdb2/__init__.py | 23 ++- glances/exports/glances_json/__init__.py | 14 +- glances/exports/glances_kafka/__init__.py | 15 +- glances/exports/glances_mongodb/__init__.py | 11 +- glances/exports/glances_mqtt/__init__.py | 9 +- glances/exports/glances_opentsdb/__init__.py | 13 +- .../exports/glances_prometheus/__init__.py | 9 +- glances/exports/glances_rabbitmq/__init__.py | 7 +- glances/exports/glances_restful/__init__.py | 9 +- glances/exports/glances_riemann/__init__.py | 7 +- glances/exports/glances_statsd/__init__.py | 11 +- glances/exports/glances_zeromq/__init__.py | 13 +- glances/filter.py | 9 +- glances/folder_list.py | 5 +- glances/globals.py | 7 +- glances/history.py | 3 +- glances/logger.py | 5 +- glances/main.py | 27 ++-- glances/outdated.py | 21 ++- glances/outputs/glances_bars.py | 7 +- glances/outputs/glances_curses.py | 43 +++-- glances/outputs/glances_curses_browser.py | 29 ++-- glances/outputs/glances_restful_api.py | 147 ++++++++---------- glances/outputs/glances_sparklines.py | 11 +- glances/outputs/glances_stdout.py | 13 +- glances/outputs/glances_stdout_apidoc.py | 49 +++--- glances/outputs/glances_stdout_csv.py | 17 +- glances/outputs/glances_stdout_issue.py | 25 +-- glances/outputs/glances_stdout_json.py | 5 +- glances/outputs/glances_unicode.py | 1 - glances/password.py | 11 +- glances/password_list.py | 9 +- glances/plugins/alert/__init__.py | 7 +- glances/plugins/amps/__init__.py | 9 +- glances/plugins/cloud/__init__.py | 13 +- glances/plugins/connections/__init__.py | 15 +- glances/plugins/containers/__init__.py | 21 ++- glances/plugins/containers/engines/docker.py | 13 +- glances/plugins/containers/engines/podman.py | 15 +- glances/plugins/containers/stats_streamer.py | 3 +- glances/plugins/core/__init__.py | 3 +- glances/plugins/cpu/__init__.py | 5 +- glances/plugins/diskio/__init__.py | 17 +- glances/plugins/folders/__init__.py | 9 +- glances/plugins/fs/__init__.py | 9 +- glances/plugins/gpu/__init__.py | 17 +- glances/plugins/gpu/cards/amd.py | 1 - glances/plugins/gpu/cards/nvidia.py | 5 +- glances/plugins/help/__init__.py | 15 +- glances/plugins/ip/__init__.py | 17 +- glances/plugins/irq/__init__.py | 15 +- glances/plugins/load/__init__.py | 19 ++- glances/plugins/mem/__init__.py | 5 +- glances/plugins/memswap/__init__.py | 5 +- glances/plugins/network/__init__.py | 19 +-- glances/plugins/now/__init__.py | 5 +- glances/plugins/percpu/__init__.py | 13 +- glances/plugins/plugin/model.py | 33 ++-- glances/plugins/ports/__init__.py | 29 ++-- glances/plugins/processcount/__init__.py | 13 +- glances/plugins/processlist/__init__.py | 17 +- glances/plugins/psutilversion/__init__.py | 3 +- glances/plugins/quicklook/__init__.py | 17 +- glances/plugins/raid/__init__.py | 13 +- glances/plugins/sensors/__init__.py | 23 ++- .../sensors/sensor/glances_batpercent.py | 9 +- .../plugins/sensors/sensor/glances_hddtemp.py | 9 +- glances/plugins/smart/__init__.py | 13 +- glances/plugins/system/__init__.py | 9 +- glances/plugins/uptime/__init__.py | 5 +- glances/plugins/version/__init__.py | 3 +- glances/plugins/wifi/__init__.py | 13 +- glances/ports_list.py | 27 ++-- glances/processes.py | 25 ++- glances/programs.py | 1 - glances/secure.py | 3 +- glances/server.py | 21 ++- glances/snmp.py | 5 +- glances/standalone.py | 31 ++-- glances/static_list.py | 19 ++- glances/stats.py | 21 ++- glances/stats_client.py | 9 +- glances/stats_client_snmp.py | 7 +- glances/stats_server.py | 5 +- glances/thresholds.py | 5 +- glances/timer.py | 5 +- glances/web_list.py | 29 ++-- glances/webserver.py | 3 +- pyproject.toml | 2 +- run.py | 1 - setup.py | 15 +- unittest-core.py | 79 +++++----- unittest-restful.py | 93 ++++++----- unittest-xmlrpc.py | 35 ++--- 120 files changed, 835 insertions(+), 1060 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5cdfc920..de8ac1c7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Glances documentation build configuration file, created by # sphinx-quickstart on Tue Mar 1 10:53:59 2016. diff --git a/glances/__init__.py b/glances/__init__.py index a96d0a06..e8ff04cb 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -44,11 +43,6 @@ try: except locale.Error: print("Warning: Unable to set locale. Expect encoding problems.") -# Check Python version -if sys.version_info < (3, 4): - print('Glances requires at least Python 3.4 to run.') - sys.exit(1) - # Check psutil version psutil_min_version = (5, 3, 0) psutil_version_info = tuple([int(num) for num in psutil_version.split('.')]) @@ -56,11 +50,12 @@ if psutil_version_info < psutil_min_version: print('psutil 5.3.0 or higher is needed. Glances cannot start.') sys.exit(1) + # Trac malloc is only available on Python 3.4 or higher def __signal_handler(signal, frame): - logger.debug("Signal {} catched".format(signal)) + logger.debug(f"Signal {signal} catched") end() @@ -103,20 +98,16 @@ def start(config, args): from glances.webserver import GlancesWebServer as GlancesMode # Init the mode - logger.info("Start {} mode".format(GlancesMode.__name__)) + logger.info(f"Start {GlancesMode.__name__} mode") mode = GlancesMode(config=config, args=args) # Start the main loop - logger.debug("Glances started in {} seconds".format(start_duration.get())) + logger.debug(f"Glances started in {start_duration.get()} seconds") if args.stop_after: - logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time)) + logger.info(f'Glances will be stopped in ~{args.stop_after * args.time} seconds') if args.memory_leak: - print( - 'Memory leak detection, please wait ~{} seconds...'.format( - args.stop_after * args.time * args.memory_leak * 2 - ) - ) + print(f'Memory leak detection, please wait ~{args.stop_after * args.time * args.memory_leak * 2} seconds...') # First run without dump to fill the memory mode.serve_n(args.stop_after) # Then start the memory-leak loop @@ -133,7 +124,7 @@ def start(config, args): snapshot_end = tracemalloc.take_snapshot() snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') memory_leak = sum([s.size_diff for s in snapshot_diff]) - print("Memory consumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000)) + print(f"Memory consumption: {memory_leak / 1000:.1f}KB (see log for details)") logger.info("Memory consumption (top 5):") for stat in snapshot_diff[:5]: logger.info(stat) @@ -165,12 +156,10 @@ def main(): signal.signal(sig, __signal_handler) # Log Glances and psutil version - logger.info('Start Glances {}'.format(__version__)) - logger.info( - '{} {} ({}) and psutil {} detected'.format( - platform.python_implementation(), platform.python_version(), sys.executable, psutil_version - ) - ) + logger.info(f'Start Glances {__version__}') + python_impl = platform.python_implementation() + python_ver = platform.python_version() + logger.info(f'{python_impl} {python_ver} ({sys.executable}) and psutil {psutil_version} detected') # Share global var global core diff --git a/glances/__main__.py b/glances/__main__.py index 0da0b639..58cca551 100644 --- a/glances/__main__.py +++ b/glances/__main__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Glances - An eye on your system # diff --git a/glances/actions.py b/glances/actions.py index 192749b2..5ea247bb 100644 --- a/glances/actions.py +++ b/glances/actions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ else: chevron_tag = True -class GlancesActions(object): +class GlancesActions: """This class manage action if an alert is reached.""" def __init__(self, args=None): @@ -80,13 +79,13 @@ class GlancesActions(object): else: cmd_full = cmd # Execute the action - logger.info("Action triggered for {} ({}): {}".format(stat_name, criticality, cmd_full)) + logger.info(f"Action triggered for {stat_name} ({criticality}): {cmd_full}") try: ret = secure_popen(cmd_full) except OSError as e: - logger.error("Action error for {} ({}): {}".format(stat_name, criticality, e)) + logger.error(f"Action error for {stat_name} ({criticality}): {e}") else: - logger.debug("Action result for {} ({}): {}".format(stat_name, criticality, ret)) + logger.debug(f"Action result for {stat_name} ({criticality}): {ret}") self.set(stat_name, criticality) diff --git a/glances/amps/amp.py b/glances/amps/amp.py index 61a3b0a4..e657f80a 100644 --- a/glances/amps/amp.py +++ b/glances/amps/amp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -27,7 +26,7 @@ from glances.logger import logger from glances.timer import Timer -class GlancesAmp(object): +class GlancesAmp: """Main class for Glances AMP.""" NAME = '?' @@ -38,7 +37,7 @@ class GlancesAmp(object): def __init__(self, name=None, args=None): """Init AMP class.""" - logger.debug("AMP - Init {} version {}".format(self.NAME, self.VERSION)) + logger.debug(f"AMP - Init {self.NAME} version {self.VERSION}") # AMP name (= module name without glances_) if name is None: @@ -74,7 +73,7 @@ class GlancesAmp(object): amp_section = 'amp_' + self.amp_name if hasattr(config, 'has_section') and config.has_section(amp_section): - logger.debug("AMP - {}: Load configuration".format(self.NAME)) + logger.debug(f"AMP - {self.NAME}: Load configuration") for param, _ in config.items(amp_section): try: self.configs[param] = config.get_float_value(amp_section, param) @@ -82,9 +81,9 @@ class GlancesAmp(object): self.configs[param] = config.get_value(amp_section, param).split(',') if len(self.configs[param]) == 1: self.configs[param] = self.configs[param][0] - logger.debug("AMP - {}: Load parameter: {} = {}".format(self.NAME, param, self.configs[param])) + logger.debug(f"AMP - {self.NAME}: Load parameter: {param} = {self.configs[param]}") else: - logger.debug("AMP - {}: Can not find section {} in the configuration file".format(self.NAME, self.amp_name)) + logger.debug(f"AMP - {self.NAME}: Can not find section {self.amp_name} in the configuration file") return False if self.enable(): @@ -92,13 +91,12 @@ class GlancesAmp(object): for k in ['refresh']: if k not in self.configs: logger.warning( - "AMP - {}: Can not find configuration key {} in section {} (the AMP will be disabled)".format( - self.NAME, k, self.amp_name - ) + f"AMP - {self.NAME}: Can not find configuration key {k} in section {self.amp_name} " + f"(the AMP will be disabled)" ) self.configs['enable'] = 'false' else: - logger.debug("AMP - {} is disabled".format(self.NAME)) + logger.debug(f"AMP - {self.NAME} is disabled") # Init the count to 0 self.configs['count'] = 0 diff --git a/glances/amps/default/__init__.py b/glances/amps/default/__init__.py index 444ce053..793847cd 100644 --- a/glances/amps/default/__init__.py +++ b/glances/amps/default/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -44,7 +43,7 @@ class Amp(GlancesAmp): def __init__(self, name=None, args=None): """Init the AMP.""" self.NAME = name.capitalize() - super(Amp, self).__init__(name=name, args=args) + super().__init__(name=name, args=args) def update(self, process_list): """Update the AMP""" @@ -54,7 +53,7 @@ class Amp(GlancesAmp): try: res = self.get('command') except OSError as e: - logger.debug('{}: Error while executing command ({})'.format(self.NAME, e)) + logger.debug(f'{self.NAME}: Error while executing command ({e})') return self.result() # No command found, use default message if res is None: diff --git a/glances/amps/nginx/__init__.py b/glances/amps/nginx/__init__.py index e8ecb829..7aa43e13 100644 --- a/glances/amps/nginx/__init__.py +++ b/glances/amps/nginx/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # diff --git a/glances/amps/systemd/__init__.py b/glances/amps/systemd/__init__.py index f1b8013f..24fbe809 100644 --- a/glances/amps/systemd/__init__.py +++ b/glances/amps/systemd/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -62,7 +61,7 @@ class Amp(GlancesAmp): try: res = check_output(self.get('systemctl_cmd').split()) except (OSError, CalledProcessError) as e: - logger.debug('{}: Error while executing systemctl ({})'.format(self.NAME, e)) + logger.debug(f'{self.NAME}: Error while executing systemctl ({e})') else: status = {} # For each line @@ -79,7 +78,7 @@ class Amp(GlancesAmp): # Build the output (string) message output = 'Services\n' for k, v in iteritems(status): - output += '{}: {}\n'.format(k, v) + output += f'{k}: {v}\n' self.set_result(output, separator=' ') return self.result() diff --git a/glances/amps/systemv/__init__.py b/glances/amps/systemv/__init__.py index ce5676a1..7d53d568 100644 --- a/glances/amps/systemv/__init__.py +++ b/glances/amps/systemv/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -61,7 +60,7 @@ class Amp(GlancesAmp): try: res = check_output(self.get('service_cmd').split(), stderr=STDOUT).decode('utf-8') except OSError as e: - logger.debug('{}: Error while executing service ({})'.format(self.NAME, e)) + logger.debug(f'{self.NAME}: Error while executing service ({e})') else: status = {'running': 0, 'stopped': 0, 'upstart': 0} # For each line @@ -79,7 +78,7 @@ class Amp(GlancesAmp): # Build the output (string) message output = 'Services\n' for k, v in iteritems(status): - output += '{}: {}\n'.format(k, v) + output += f'{k}: {v}\n' self.set_result(output, separator=' ') return self.result() diff --git a/glances/amps_list.py b/glances/amps_list.py index 9feccb5f..98fddff9 100644 --- a/glances/amps_list.py +++ b/glances/amps_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -18,7 +17,7 @@ from glances.logger import logger from glances.processes import glances_processes -class AmpsList(object): +class AmpsList: """This class describes the optional application monitoring process list. The AMP list is a list of processes with a specific monitoring action. @@ -57,9 +56,9 @@ class AmpsList(object): try: amp = __import__(os.path.basename(amp_module)) except ImportError as e: - logger.warning("Missing Python Lib ({}), cannot load AMP {}".format(e, amp_name)) + logger.warning(f"Missing Python Lib ({e}), cannot load AMP {amp_name}") except Exception as e: - logger.warning("Cannot load AMP {} ({})".format(amp_name, e)) + logger.warning(f"Cannot load AMP {amp_name} ({e})") else: # Add the AMP to the dictionary # The key is the AMP name @@ -69,7 +68,7 @@ class AmpsList(object): # Load the AMP configuration self.__amps_dict[amp_name].load_config(self.config) # Log AMPs list - logger.debug("AMPs list: {}".format(self.getList())) + logger.debug(f"AMPs list: {self.getList()}") return True @@ -108,7 +107,7 @@ class AmpsList(object): if len(amps_list) > 0: # At least one process is matching the regex - logger.debug("AMPS: {} processes {} detected ({})".format(len(amps_list), k, amps_list)) + logger.debug(f"AMPS: {len(amps_list)} processes {k} detected ({amps_list})") # Call the AMP update method thread = threading.Thread(target=v.update_wrapper, args=[amps_list]) thread.start() @@ -140,7 +139,7 @@ class AmpsList(object): ) except (TypeError, KeyError) as e: - logger.debug("Can not build AMPS list ({})".format(e)) + logger.debug(f"Can not build AMPS list ({e})") return ret diff --git a/glances/attribute.py b/glances/attribute.py index 22f25ef2..63ad1113 100644 --- a/glances/attribute.py +++ b/glances/attribute.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -12,7 +11,7 @@ from datetime import datetime -class GlancesAttribute(object): +class GlancesAttribute: def __init__(self, name, description='', history_max_size=None): """Init the attribute diff --git a/glances/autodiscover.py b/glances/autodiscover.py index 9b784697..8be3c2a8 100644 --- a/glances/autodiscover.py +++ b/glances/autodiscover.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -27,7 +26,7 @@ except ImportError: if zeroconf_tag: zeroconf_min_version = (0, 17, 0) zeroconf_version = tuple([int(num) for num in __zeroconf_version.split('.')]) - logger.debug("Zeroconf version {} detected.".format(__zeroconf_version)) + logger.debug(f"Zeroconf version {__zeroconf_version} detected.") if zeroconf_version < zeroconf_min_version: logger.critical("Please install zeroconf 0.17 or higher.") sys.exit(1) @@ -35,10 +34,10 @@ if zeroconf_tag: # Global var # Recent versions of the zeroconf python package doesn't like a zeroconf type that ends with '._tcp.'. # Correct issue: zeroconf problem with zeroconf_type = "_%s._tcp." % 'glances' #888 -zeroconf_type = "_%s._tcp.local." % 'glances' +zeroconf_type = "_{}._tcp.local.".format('glances') -class AutoDiscovered(object): +class AutoDiscovered: """Class to manage the auto discovered servers dict.""" def __init__(self): @@ -67,7 +66,7 @@ class AutoDiscovered(object): 'type': 'DYNAMIC', } # Server type: 'STATIC' or 'DYNAMIC' self._server_list.append(new_server) - logger.debug("Updated servers list (%s servers): %s" % (len(self._server_list), self._server_list)) + logger.debug(f"Updated servers list ({len(self._server_list)} servers): {self._server_list}") def remove_server(self, name): """Remove a server from the dict.""" @@ -75,13 +74,13 @@ class AutoDiscovered(object): if i['key'] == name: try: self._server_list.remove(i) - logger.debug("Remove server %s from the list" % name) - logger.debug("Updated servers list (%s servers): %s" % (len(self._server_list), self._server_list)) + logger.debug(f"Remove server {name} from the list") + logger.debug(f"Updated servers list ({len(self._server_list)} servers): {self._server_list}") except ValueError: - logger.error("Cannot remove server %s from the list" % name) + logger.error(f"Cannot remove server {name} from the list") -class GlancesAutoDiscoverListener(object): +class GlancesAutoDiscoverListener: """Zeroconf listener for Glances server.""" def __init__(self): @@ -105,7 +104,7 @@ class GlancesAutoDiscoverListener(object): """ if srv_type != zeroconf_type: return False - logger.debug("Check new Zeroconf server: %s / %s" % (srv_type, srv_name)) + logger.debug(f"Check new Zeroconf server: {srv_type} / {srv_name}") info = zeroconf.get_service_info(srv_type, srv_name) if info and (info.addresses or info.parsed_addresses): address = info.addresses[0] if info.addresses else info.parsed_addresses[0] @@ -114,7 +113,7 @@ class GlancesAutoDiscoverListener(object): # Add server to the global dict self.servers.add_server(srv_name, new_server_ip, new_server_port) - logger.info("New Glances server detected (%s from %s:%s)" % (srv_name, new_server_ip, new_server_port)) + logger.info(f"New Glances server detected ({srv_name} from {new_server_ip}:{new_server_port})") else: logger.warning("New Glances server detected, but failed to be get Zeroconf ServiceInfo ") return True @@ -122,10 +121,10 @@ class GlancesAutoDiscoverListener(object): def remove_service(self, zeroconf, srv_type, srv_name): """Remove the server from the list.""" self.servers.remove_server(srv_name) - logger.info("Glances server %s removed from the autodetect list" % srv_name) + logger.info(f"Glances server {srv_name} removed from the autodetect list") -class GlancesAutoDiscoverServer(object): +class GlancesAutoDiscoverServer: """Implementation of the Zeroconf protocol (server side for the Glances client).""" def __init__(self, args=None): @@ -133,8 +132,8 @@ class GlancesAutoDiscoverServer(object): logger.info("Init autodiscover mode (Zeroconf protocol)") try: self.zeroconf = Zeroconf() - except socket.error as e: - logger.error("Cannot start Zeroconf (%s)" % e) + except OSError as e: + logger.error(f"Cannot start Zeroconf ({e})") self.zeroconf_enable_tag = False else: self.listener = GlancesAutoDiscoverListener() @@ -160,7 +159,7 @@ class GlancesAutoDiscoverServer(object): self.zeroconf.close() -class GlancesAutoDiscoverClient(object): +class GlancesAutoDiscoverClient: """Implementation of the zeroconf protocol (client side for the Glances server).""" def __init__(self, hostname, args=None): @@ -168,8 +167,8 @@ class GlancesAutoDiscoverClient(object): zeroconf_bind_address = args.bind_address try: self.zeroconf = Zeroconf() - except socket.error as e: - logger.error("Cannot start zeroconf: {}".format(e)) + except OSError as e: + logger.error(f"Cannot start zeroconf: {e}") # XXX *BSDs: Segmentation fault (core dumped) # -- https://bitbucket.org/al45tair/netifaces/issues/15 @@ -192,7 +191,7 @@ class GlancesAutoDiscoverClient(object): try: self.info = ServiceInfo( zeroconf_type, - '{}:{}.{}'.format(hostname, args.port, zeroconf_type), + f'{hostname}:{args.port}.{zeroconf_type}', address=socket.inet_pton(address_family, zeroconf_bind_address), port=args.port, weight=0, @@ -205,7 +204,7 @@ class GlancesAutoDiscoverClient(object): # address (only one address) is replaced by addresses (list of addresses) self.info = ServiceInfo( zeroconf_type, - name='{}:{}.{}'.format(hostname, args.port, zeroconf_type), + name=f'{hostname}:{args.port}.{zeroconf_type}', addresses=[socket.inet_pton(address_family, zeroconf_bind_address)], port=args.port, weight=0, @@ -216,9 +215,9 @@ class GlancesAutoDiscoverClient(object): try: self.zeroconf.register_service(self.info) except Exception as e: - logger.error("Error while announcing Glances server: {}".format(e)) + logger.error(f"Error while announcing Glances server: {e}") else: - print("Announce the Glances server on the LAN (using {} IP address)".format(zeroconf_bind_address)) + print(f"Announce the Glances server on the LAN (using {zeroconf_bind_address} IP address)") else: logger.error("Cannot announce Glances server on the network: zeroconf library not found.") diff --git a/glances/client.py b/glances/client.py index c4cfe185..8e598635 100644 --- a/glances/client.py +++ b/glances/client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,7 +8,6 @@ """Manage the Glances client.""" -import socket import sys import time @@ -30,7 +28,7 @@ class GlancesClientTransport(Transport): self.timeout = timeout -class GlancesClient(object): +class GlancesClient: """This class creates and manages the TCP client.""" def __init__(self, config=None, args=None, timeout=7, return_to_browser=False): @@ -49,10 +47,10 @@ class GlancesClient(object): # Build the URI if args.password != "": - self.uri = 'http://{}:{}@{}:{}'.format(args.username, args.password, args.client, args.port) + self.uri = f'http://{args.username}:{args.password}@{args.client}:{args.port}' else: - self.uri = 'http://{}:{}'.format(args.client, args.port) - logger.debug("Try to connect to {}".format(self.uri)) + self.uri = f'http://{args.client}:{args.port}' + logger.debug(f"Try to connect to {self.uri}") # Try to connect to the URI transport = GlancesClientTransport() @@ -61,7 +59,7 @@ class GlancesClient(object): try: self.client = ServerProxy(self.uri, transport=transport) except Exception as e: - self.log_and_exit("Client couldn't create socket {}: {}".format(self.uri, e)) + self.log_and_exit(f"Client couldn't create socket {self.uri}: {e}") @property def quiet(self): @@ -94,10 +92,10 @@ class GlancesClient(object): client_version = None try: client_version = self.client.init() - except socket.error as err: + except OSError as err: # Fallback to SNMP self.client_mode = 'snmp' - logger.error("Connection to Glances server failed ({} {})".format(err.errno, err.strerror)) + logger.error(f"Connection to Glances server failed ({err.errno} {err.strerror})") fall_back_msg = 'No Glances server found. Trying fallback to SNMP...' if not self.return_to_browser: print(fall_back_msg) @@ -105,11 +103,11 @@ class GlancesClient(object): logger.info(fall_back_msg) except ProtocolError as err: # Other errors - msg = "Connection to server {} failed".format(self.uri) + msg = f"Connection to server {self.uri} failed" if err.errcode == 401: msg += " (Bad username/password)" else: - msg += " ({} {})".format(err.errcode, err.errmsg) + msg += f" ({err.errcode} {err.errmsg})" self.log_and_exit(msg) return False @@ -119,14 +117,11 @@ class GlancesClient(object): # Init stats self.stats = GlancesStatsClient(config=self.config, args=self.args) self.stats.set_plugins(ujson.loads(self.client.getAllPlugins())) - logger.debug("Client version: {} / Server version: {}".format(__version__, client_version)) + logger.debug(f"Client version: {__version__} / Server version: {client_version}") else: self.log_and_exit( - ( - 'Client and server not compatible: ' 'Client version: {} / Server version: {}'.format( - __version__, client_version - ) - ) + 'Client and server not compatible: ' + f'Client version: {__version__} / Server version: {client_version}' ) return False @@ -186,7 +181,7 @@ class GlancesClient(object): return self.update_snmp() self.end() - logger.critical("Unknown server mode: {}".format(self.client_mode)) + logger.critical(f"Unknown server mode: {self.client_mode}") sys.exit(2) def update_glances(self): @@ -199,7 +194,7 @@ class GlancesClient(object): # Update the stats try: server_stats = ujson.loads(self.client.getAll()) - except socket.error: + except OSError: # Client cannot get server stats return "Disconnected" except Fault: @@ -242,12 +237,12 @@ class GlancesClient(object): # Update the stats counter = Counter() cs_status = self.update() - logger.debug('Stats updated duration: {} seconds'.format(counter.get())) + logger.debug(f'Stats updated duration: {counter.get()} seconds') # Export stats using export modules counter_export = Counter() self.stats.export(self.stats) - logger.debug('Stats exported duration: {} seconds'.format(counter_export.get())) + logger.debug(f'Stats exported duration: {counter_export.get()} seconds') # Patch for issue1326 to avoid < 0 refresh adapted_refresh = self.refresh_time - counter.get() diff --git a/glances/client_browser.py b/glances/client_browser.py index 1409d316..4e98cde4 100644 --- a/glances/client_browser.py +++ b/glances/client_browser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,7 +8,6 @@ """Manage the Glances client browser (list of Glances server).""" -import socket import threading import ujson @@ -23,7 +21,7 @@ from glances.password_list import GlancesPasswordList as GlancesPassword from glances.static_list import GlancesStaticServer -class GlancesClientBrowser(object): +class GlancesClientBrowser: """This class creates and manages the TCP client browser (servers list).""" def __init__(self, config=None, args=None): @@ -92,19 +90,19 @@ class GlancesClientBrowser(object): try: s = ServerProxy(uri, transport=t) except Exception as e: - logger.warning("Client browser couldn't create socket ({})".format(e)) + logger.warning(f"Client browser couldn't create socket ({e})") else: # Mandatory stats try: # CPU% cpu_percent = 100 - ujson.loads(s.getCpu())['idle'] - server['cpu_percent'] = '{:.1f}'.format(cpu_percent) + server['cpu_percent'] = f'{cpu_percent:.1f}' # MEM% server['mem_percent'] = ujson.loads(s.getMem())['percent'] # OS (Human Readable name) server['hr_name'] = ujson.loads(s.getSystem())['hr_name'] - except (socket.error, Fault, KeyError) as e: - logger.debug("Error while grabbing stats form server ({})".format(e)) + except (OSError, Fault, KeyError) as e: + logger.debug(f"Error while grabbing stats form server ({e})") server['status'] = 'OFFLINE' except ProtocolError as e: if e.errcode == 401: @@ -114,7 +112,7 @@ class GlancesClientBrowser(object): server['status'] = 'PROTECTED' else: server['status'] = 'OFFLINE' - logger.debug("Cannot grab stats from server ({} {})".format(e.errcode, e.errmsg)) + logger.debug(f"Cannot grab stats from server ({e.errcode} {e.errmsg})") else: # Status server['status'] = 'ONLINE' @@ -123,16 +121,16 @@ class GlancesClientBrowser(object): try: # LOAD load_min5 = ujson.loads(s.getLoad())['min5'] - server['load_min5'] = '{:.2f}'.format(load_min5) + server['load_min5'] = f'{load_min5:.2f}' except Exception as e: - logger.warning("Error while grabbing stats form server ({})".format(e)) + logger.warning(f"Error while grabbing stats form server ({e})") return server def __display_server(self, server): """Connect and display the given server""" # Display the Glances client for the selected server - logger.debug("Selected server {}".format(server)) + logger.debug(f"Selected server {server}") # Connection can take time # Display a popup @@ -201,7 +199,7 @@ class GlancesClientBrowser(object): # For each server in the list, grab elementary stats (CPU, LOAD, MEM, OS...) thread_list = {} while not self.screen.is_end: - logger.debug("Iter through the following server list: {}".format(self.get_servers_list())) + logger.debug(f"Iter through the following server list: {self.get_servers_list()}") for v in self.get_servers_list(): key = v["key"] thread = thread_list.get(key, None) diff --git a/glances/config.py b/glances/config.py index 8f263296..a59a837f 100644 --- a/glances/config.py +++ b/glances/config.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,11 +8,11 @@ """Manage the configuration file.""" +import builtins import multiprocessing import os import re import sys -from io import open from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, ConfigParser, NoOptionError, NoSectionError, system_exec from glances.logger import logger @@ -94,7 +93,7 @@ def default_config_dir(): return [path] -class Config(object): +class Config: """This class is used to access/read config file, if it exists. :param config_dir: the path to search for config file @@ -153,15 +152,15 @@ class Config(object): def read(self): """Read the config file, if it exists. Using defaults otherwise.""" for config_file in self.config_file_paths(): - logger.debug('Search glances.conf file in {}'.format(config_file)) + logger.debug(f'Search glances.conf file in {config_file}') if os.path.exists(config_file): try: - with open(config_file, encoding='utf-8') as f: + with builtins.open(config_file, encoding='utf-8') as f: self.parser.read_file(f) self.parser.read(f) - logger.info("Read configuration file '{}'".format(config_file)) + logger.info(f"Read configuration file '{config_file}'") except UnicodeDecodeError as err: - logger.error("Can not read configuration file '{}': {}".format(config_file, err)) + logger.error(f"Can not read configuration file '{config_file}': {err}") sys.exit(1) # Save the loaded configuration file path (issue #374) self._loaded_config_file = config_file diff --git a/glances/cpu_percent.py b/glances/cpu_percent.py index e6fe96ec..b02ca82b 100644 --- a/glances/cpu_percent.py +++ b/glances/cpu_percent.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -15,7 +14,7 @@ from glances.logger import logger from glances.timer import Timer -class CpuPercent(object): +class CpuPercent: """Get and store the CPU percent.""" def __init__(self, cached_timer_cpu=3): @@ -56,7 +55,7 @@ class CpuPercent(object): try: cpu_freq = psutil.cpu_freq() except Exception as e: - logger.debug('Can not grab CPU information ({})'.format(e)) + logger.debug(f'Can not grab CPU information ({e})') else: if hasattr(cpu_freq, 'current'): self.cpu_info['cpu_hz_current'] = cpu_freq.current @@ -74,7 +73,7 @@ class CpuPercent(object): # Get the CPU name once from the /proc/cpuinfo file # TODO: Multisystem... try: - self.cpu_info['cpu_name'] = open('/proc/cpuinfo', 'r').readlines()[4].split(':')[1].strip() + self.cpu_info['cpu_name'] = open('/proc/cpuinfo').readlines()[4].split(':')[1].strip() except (FileNotFoundError, PermissionError, IndexError, KeyError, AttributeError): self.cpu_info['cpu_name'] = 'CPU' return self.cpu_info['cpu_name'] diff --git a/glances/event.py b/glances/event.py index ea2f3cbe..318faa9a 100644 --- a/glances/event.py +++ b/glances/event.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # diff --git a/glances/events_list.py b/glances/events_list.py index e1105d5f..8e2e4fae 100644 --- a/glances/events_list.py +++ b/glances/events_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -161,7 +160,7 @@ def build_global_message(): return tree[0]['msg'] -class GlancesEventsList(object): +class GlancesEventsList: """This class manages events inside the Glances software. GlancesEventsList is a list of GlancesEvent. GlancesEvent is defined in the event.py file diff --git a/glances/exports/export.py b/glances/exports/export.py index b92654ea..0241e1b8 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -18,7 +17,7 @@ from glances.logger import logger from glances.timer import Counter -class GlancesExport(object): +class GlancesExport: """Main class for Glances export IF.""" # List of non exportable plugins @@ -39,7 +38,7 @@ class GlancesExport(object): """Init the export class.""" # Export name self.export_name = self.__class__.__module__ - logger.debug("Init export module %s" % self.export_name) + logger.debug(f"Init export module {self.export_name}") # Init the config & args self.config = config @@ -63,18 +62,16 @@ class GlancesExport(object): counter = Counter() ret = fct(*args, **kw) duration = counter.get() - logger.debug( - "{} {} {} return {} in {} seconds".format( - args[0].__class__.__name__, args[0].__class__.__module__, fct.__name__, ret, duration - ) - ) + class_name = args[0].__class__.__name__ + class_module = args[0].__class__.__module__ + logger.debug(f"{class_name} {class_module} {fct.__name__} return {ret} in {duration} seconds") return ret return wrapper def exit(self): """Close the export module.""" - logger.debug("Finalise export interface %s" % self.export_name) + logger.debug(f"Finalise export interface {self.export_name}") def load_conf(self, section, mandatories=['host', 'port'], options=None): """Load the export
configuration in the Glances configuration file. @@ -95,10 +92,10 @@ class GlancesExport(object): for opt in mandatories: setattr(self, opt, self.config.get_value(section, opt)) except NoSectionError: - logger.error("No {} configuration found".format(section)) + logger.error(f"No {section} configuration found") return False except NoOptionError as e: - logger.error("Error in the {} configuration ({})".format(section, e)) + logger.error(f"Error in the {section} configuration ({e})") return False # Load options @@ -108,8 +105,8 @@ class GlancesExport(object): except NoOptionError: pass - logger.debug("Load {} from the Glances configuration file".format(section)) - logger.debug("{} parameters: {}".format(section, {opt: getattr(self, opt) for opt in mandatories + options})) + logger.debug(f"Load {section} from the Glances configuration file") + logger.debug(f"{section} parameters: {({opt: getattr(self, opt) for opt in mandatories + options})}") return True @@ -119,7 +116,7 @@ class GlancesExport(object): try: ret = item[item['key']] except KeyError: - logger.error("No 'key' available in {}".format(item)) + logger.error(f"No 'key' available in {item}") if isinstance(ret, list): return ret[0] return ret diff --git a/glances/exports/glances_cassandra/__init__.py b/glances/exports/glances_cassandra/__init__.py index 75f591b7..4325a63b 100644 --- a/glances/exports/glances_cassandra/__init__.py +++ b/glances/exports/glances_cassandra/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -27,7 +26,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Cassandra export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.keyspace = None @@ -69,53 +68,52 @@ class Export(GlancesExport): ) session = cluster.connect() except Exception as e: - logger.critical("Cannot connect to Cassandra cluster '%s:%s' (%s)" % (self.host, self.port, e)) + logger.critical(f"Cannot connect to Cassandra cluster '{self.host}:{self.port}' ({e})") sys.exit(2) # Keyspace try: session.set_keyspace(self.keyspace) except InvalidRequest: - logger.info("Create keyspace {} on the Cassandra cluster".format(self.keyspace)) - c = "CREATE KEYSPACE %s WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '%s' }" % ( - self.keyspace, - self.replication_factor, + logger.info(f"Create keyspace {self.keyspace} on the Cassandra cluster") + c = ( + f"CREATE KEYSPACE {self.keyspace} WITH " + f"replication = {{ 'class': 'SimpleStrategy', 'replication_factor': '{self.replication_factor}' }}" ) session.execute(c) session.set_keyspace(self.keyspace) logger.info( - "Stats will be exported to Cassandra cluster {} ({}) in keyspace {}".format( - cluster.metadata.cluster_name, cluster.metadata.all_hosts(), self.keyspace - ) + f"Stats will be exported to Cassandra cluster {cluster.metadata.cluster_name} " + f"({cluster.metadata.all_hosts()}) in keyspace {self.keyspace}" ) # Table try: session.execute( - "CREATE TABLE %s (plugin text, time timeuuid, stat map, PRIMARY KEY (plugin, time)) \ - WITH CLUSTERING ORDER BY (time DESC)" - % self.table + f"CREATE TABLE {self.table} " + f"(plugin text, time timeuuid, stat map, PRIMARY KEY (plugin, time)) " + f"WITH CLUSTERING ORDER BY (time DESC)" ) except Exception: - logger.debug("Cassandra table %s already exist" % self.table) + logger.debug(f"Cassandra table {self.table} already exist") return cluster, session def export(self, name, columns, points): """Write the points to the Cassandra cluster.""" - logger.debug("Export {} stats to Cassandra".format(name)) + logger.debug(f"Export {name} stats to Cassandra") # Remove non number stats and convert all to float (for Boolean) data = {k: float(v) for (k, v) in dict(zip(columns, points)).iteritems() if isinstance(v, Number)} # Write input to the Cassandra table try: - stmt = "INSERT INTO {} (plugin, time, stat) VALUES (?, ?, ?)".format(self.table) + stmt = f"INSERT INTO {self.table} (plugin, time, stat) VALUES (?, ?, ?)" query = self.session.prepare(stmt) self.session.execute(query, (name, uuid_from_time(datetime.now()), data)) except Exception as e: - logger.error("Cannot export {} stats to Cassandra ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to Cassandra ({e})") def exit(self): """Close the Cassandra export module.""" @@ -123,4 +121,4 @@ class Export(GlancesExport): self.session.shutdown() self.cluster.shutdown() # Call the father method - super(Export, self).exit() + super().exit() diff --git a/glances/exports/glances_couchdb/__init__.py b/glances/exports/glances_couchdb/__init__.py index 02fd62f6..4bedf4f3 100644 --- a/glances/exports/glances_couchdb/__init__.py +++ b/glances/exports/glances_couchdb/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -31,7 +30,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the CouchDB export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Load the CouchDB configuration file section # User and Password are mandatory with CouchDB 3.0 and higher @@ -48,15 +47,15 @@ class Export(GlancesExport): return None # @TODO: https - server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port) + server_uri = f'http://{self.user}:{self.password}@{self.host}:{self.port}/' try: s = pycouchdb.Server(server_uri) except Exception as e: - logger.critical("Cannot connect to CouchDB server (%s)" % e) + logger.critical(f"Cannot connect to CouchDB server ({e})") sys.exit(2) else: - logger.info("Connected to the CouchDB server version %s" % s.info()['version']) + logger.info("Connected to the CouchDB server version {}".format(s.info()['version'])) try: s.database(self.db) @@ -64,15 +63,15 @@ class Export(GlancesExport): # Database did not exist # Create it... s.create(self.db) - logger.info("Create CouchDB database %s" % self.db) + logger.info(f"Create CouchDB database {self.db}") else: - logger.info("CouchDB database %s already exist" % self.db) + logger.info(f"CouchDB database {self.db} already exist") return s.database(self.db) def export(self, name, columns, points): """Write the points to the CouchDB server.""" - logger.debug("Export {} stats to CouchDB".format(name)) + logger.debug(f"Export {name} stats to CouchDB") # Create DB input data = dict(zip(columns, points)) @@ -85,4 +84,4 @@ class Export(GlancesExport): try: self.client.save(data) except Exception as e: - logger.error("Cannot export {} stats to CouchDB ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to CouchDB ({e})") diff --git a/glances/exports/glances_csv/__init__.py b/glances/exports/glances_csv/__init__.py index a881bdb0..0e4ca387 100644 --- a/glances/exports/glances_csv/__init__.py +++ b/glances/exports/glances_csv/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the CSV export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # CSV file name self.csv_filename = args.export_csv_file @@ -42,8 +41,8 @@ class Export(GlancesExport): try: self.csv_file = open_csv_file(self.csv_filename, 'r') reader = csv.reader(self.csv_file) - except IOError as e: - logger.critical("Cannot open existing CSV file: {}".format(e)) + except OSError as e: + logger.critical(f"Cannot open existing CSV file: {e}") sys.exit(2) self.old_header = next(reader, None) self.csv_file.close() @@ -51,11 +50,11 @@ class Export(GlancesExport): try: self.csv_file = open_csv_file(self.csv_filename, file_mode) self.writer = csv.writer(self.csv_file) - except IOError as e: - logger.critical("Cannot create the CSV file: {}".format(e)) + except OSError as e: + logger.critical(f"Cannot create the CSV file: {e}") sys.exit(2) - logger.info("Stats exported to CSV file: {}".format(self.csv_filename)) + logger.info(f"Stats exported to CSV file: {self.csv_filename}") self.export_enable = True @@ -63,7 +62,7 @@ class Export(GlancesExport): def exit(self): """Close the CSV file.""" - logger.debug("Finalise export interface %s" % self.export_name) + logger.debug(f"Finalise export interface {self.export_name}") self.csv_file.close() def update(self, stats): @@ -95,8 +94,8 @@ class Export(GlancesExport): if self.old_header != csv_header and self.old_header is not None: # Header are different, log an error and do not write data logger.error("Cannot append data to existing CSV file. Headers are different.") - logger.debug("Old header: {}".format(self.old_header)) - logger.debug("New header: {}".format(csv_header)) + logger.debug(f"Old header: {self.old_header}") + logger.debug(f"New header: {csv_header}") else: # Header are equals, ready to write data self.old_header = None diff --git a/glances/exports/glances_elasticsearch/__init__.py b/glances/exports/glances_elasticsearch/__init__.py index 2ab17074..395f9def 100644 --- a/glances/exports/glances_elasticsearch/__init__.py +++ b/glances/exports/glances_elasticsearch/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the ES export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.index = None @@ -44,24 +43,22 @@ class Export(GlancesExport): return None try: - es = Elasticsearch(hosts=['{}://{}:{}'.format(self.scheme, self.host, self.port)]) + es = Elasticsearch(hosts=[f'{self.scheme}://{self.host}:{self.port}']) except Exception as e: - logger.critical( - "Cannot connect to ElasticSearch server %s://%s:%s (%s)" % (self.scheme, self.host, self.port, e) - ) + logger.critical(f"Cannot connect to ElasticSearch server {self.scheme}://{self.host}:{self.port} ({e})") sys.exit(2) if not es.ping(): - logger.critical("Cannot ping the ElasticSearch server %s://%s:%s" % (self.scheme, self.host, self.port)) + logger.critical(f"Cannot ping the ElasticSearch server {self.scheme}://{self.host}:{self.port}") sys.exit(2) else: - logger.info("Connected to the ElasticSearch server %s://%s:%s" % (self.scheme, self.host, self.port)) + logger.info(f"Connected to the ElasticSearch server {self.scheme}://{self.host}:{self.port}") return es def export(self, name, columns, points): """Write the points to the ES server.""" - logger.debug("Export {} stats to ElasticSearch".format(name)) + logger.debug(f"Export {name} stats to ElasticSearch") # Generate index name with the index field + current day index = '{}-{}'.format(self.index, datetime.utcnow().strftime("%Y.%m.%d")) @@ -72,17 +69,17 @@ class Export(GlancesExport): dt_now = datetime.utcnow().isoformat('T') action = { "_index": index, - "_id": '{}.{}'.format(name, dt_now), - "_type": 'glances-{}'.format(name), + "_id": f'{name}.{dt_now}', + "_type": f'glances-{name}', "_source": {"plugin": name, "timestamp": dt_now}, } action['_source'].update(zip(columns, [str(p) for p in points])) actions.append(action) - logger.debug("Exporting the following object to elasticsearch: {}".format(action)) + logger.debug(f"Exporting the following object to elasticsearch: {action}") # Write input to the ES index try: helpers.bulk(self.client, actions) except Exception as e: - logger.error("Cannot export {} stats to ElasticSearch ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to ElasticSearch ({e})") diff --git a/glances/exports/glances_graph/__init__.py b/glances/exports/glances_graph/__init__.py index 753f2e18..542be577 100644 --- a/glances/exports/glances_graph/__init__.py +++ b/glances/exports/glances_graph/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -28,7 +27,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Load the Graph configuration file section (is exists) self.export_enable = self.load_conf('graph', options=['path', 'generate_every', 'width', 'height', 'style']) @@ -45,19 +44,19 @@ class Export(GlancesExport): os.makedirs(self.path) except OSError as e: if e.errno != errno.EEXIST: - logger.critical("Cannot create the Graph output folder {} ({})".format(self.path, e)) + logger.critical(f"Cannot create the Graph output folder {self.path} ({e})") sys.exit(2) # Check if output folder is writeable try: tempfile.TemporaryFile(dir=self.path) except OSError: - logger.critical("Graph output folder {} is not writeable".format(self.path)) + logger.critical(f"Graph output folder {self.path} is not writeable") sys.exit(2) - logger.info("Graphs will be created in the {} folder".format(self.path)) + logger.info(f"Graphs will be created in the {self.path} folder") if self.generate_every != 0: - logger.info("Graphs will be created automatically every {} seconds".format(self.generate_every)) + logger.info(f"Graphs will be created automatically every {self.generate_every} seconds") logger.info("or when 'g' key is pressed (only through the CLI interface)") # Start the timer self._timer = Timer(self.generate_every) @@ -67,7 +66,7 @@ class Export(GlancesExport): def exit(self): """Close the files.""" - logger.debug("Finalise export interface %s" % self.export_name) + logger.debug(f"Finalise export interface {self.export_name}") def update(self, stats): """Generate Graph file in the output folder.""" @@ -85,7 +84,7 @@ class Export(GlancesExport): if plugin_name in self.plugins_to_export(stats): self.export(plugin_name, plugin.get_export_history()) - logger.info("Graphs created in {}".format(self.path)) + logger.info(f"Graphs created in {self.path}") self.args.generate_graph = False def export(self, title, data): diff --git a/glances/exports/glances_graphite/__init__.py b/glances/exports/glances_graphite/__init__.py index 2defe864..708e23db 100644 --- a/glances/exports/glances_graphite/__init__.py +++ b/glances/exports/glances_graphite/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Graphite export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) # N/A @@ -74,25 +73,25 @@ class Export(GlancesExport): debug=self.debug, ) except Exception as e: - logger.error("Can not write data to Graphite server: {}:{} ({})".format(self.host, self.port, e)) + logger.error(f"Can not write data to Graphite server: {self.host}:{self.port} ({e})") client = None else: - logger.info("Stats will be exported to Graphite server: {}:{}".format(self.host, self.port)) + logger.info(f"Stats will be exported to Graphite server: {self.host}:{self.port}") return client def export(self, name, columns, points): """Export the stats to the Graphite server.""" if self.client is None: return False - before_filtering_dict = dict(zip([normalize('{}.{}'.format(name, i)) for i in columns], points)) + before_filtering_dict = dict(zip([normalize(f'{name}.{i}') for i in columns], points)) after_filtering_dict = dict(filter(lambda i: isinstance(i[1], Number), before_filtering_dict.items())) try: self.client.send_dict(after_filtering_dict) except Exception as e: - logger.error("Can not export stats to Graphite (%s)" % e) + logger.error(f"Can not export stats to Graphite ({e})") return False else: - logger.debug("Export {} stats to Graphite".format(name)) + logger.debug(f"Export {name} stats to Graphite") return True diff --git a/glances/exports/glances_influxdb/__init__.py b/glances/exports/glances_influxdb/__init__.py index b1bc9a83..e2e5c6ca 100644 --- a/glances/exports/glances_influxdb/__init__.py +++ b/glances/exports/glances_influxdb/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the InfluxDB export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.user = None @@ -75,13 +74,13 @@ class Export(GlancesExport): ) get_all_db = [i['name'] for i in db.get_list_database()] except InfluxDBClientError as e: - logger.critical("Cannot connect to InfluxDB database '%s' (%s)" % (self.db, e)) + logger.critical(f"Cannot connect to InfluxDB database '{self.db}' ({e})") sys.exit(2) if self.db in get_all_db: - logger.info("Stats will be exported to InfluxDB server: {}".format(db._baseurl)) + logger.info(f"Stats will be exported to InfluxDB server: {db._baseurl}") else: - logger.critical("InfluxDB database '%s' did not exist. Please create it" % self.db) + logger.critical(f"InfluxDB database '{self.db}' did not exist. Please create it") sys.exit(2) return db @@ -106,9 +105,7 @@ class Export(GlancesExport): # Manage field if measurement is not None: fields = { - k.replace('{}.'.format(measurement), ''): data_dict[k] - for k in data_dict - if k.startswith('{}.'.format(measurement)) + k.replace(f'{measurement}.', ''): data_dict[k] for k in data_dict if k.startswith(f'{measurement}.') } else: fields = data_dict @@ -155,12 +152,12 @@ class Export(GlancesExport): name = self.prefix + '.' + name # Write input to the InfluxDB database if len(points) == 0: - logger.debug("Cannot export empty {} stats to InfluxDB".format(name)) + logger.debug(f"Cannot export empty {name} stats to InfluxDB") else: try: self.client.write_points(self._normalize(name, columns, points), time_precision="s") except Exception as e: # Log level set to debug instead of error (see: issue #1561) - logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e)) + logger.debug(f"Cannot export {name} stats to InfluxDB ({e})") else: - logger.debug("Export {} stats to InfluxDB".format(name)) + logger.debug(f"Export {name} stats to InfluxDB") diff --git a/glances/exports/glances_influxdb2/__init__.py b/glances/exports/glances_influxdb2/__init__.py index 7e10b8b3..625b9987 100644 --- a/glances/exports/glances_influxdb2/__init__.py +++ b/glances/exports/glances_influxdb2/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -25,7 +24,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the InfluxDB export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.org = None @@ -58,7 +57,7 @@ class Export(GlancesExport): self.interval = 0 # and should be set to the Glances refresh time if the value is 0 self.interval = self.interval if self.interval > 0 else self.args.time - logger.debug("InfluxDB export interval is set to {} seconds".format(self.interval)) + logger.debug(f"InfluxDB export interval is set to {self.interval} seconds") # The hostname is always add as a tag self.hostname = node().split('.')[0] @@ -71,17 +70,15 @@ class Export(GlancesExport): if not self.export_enable: return None - url = '{}://{}:{}'.format(self.protocol, self.host, self.port) + url = f'{self.protocol}://{self.host}:{self.port}' try: # See docs: https://influxdb-client.readthedocs.io/en/stable/api.html#influxdbclient client = InfluxDBClient(url=url, enable_gzip=False, verify_ssl=False, org=self.org, token=self.token) except Exception as e: - logger.critical("Cannot connect to InfluxDB server '%s' (%s)" % (url, e)) + logger.critical(f"Cannot connect to InfluxDB server '{url}' ({e})") sys.exit(2) else: - logger.info( - "Connected to InfluxDB server version {} ({})".format(client.health().version, client.health().message) - ) + logger.info(f"Connected to InfluxDB server version {client.health().version} ({client.health().message})") # Create the write client return client.write_api( @@ -116,9 +113,7 @@ class Export(GlancesExport): # Manage field if measurement is not None: fields = { - k.replace('{}.'.format(measurement), ''): data_dict[k] - for k in data_dict - if k.startswith('{}.'.format(measurement)) + k.replace(f'{measurement}.', ''): data_dict[k] for k in data_dict if k.startswith(f'{measurement}.') } else: fields = data_dict @@ -165,12 +160,12 @@ class Export(GlancesExport): name = self.prefix + '.' + name # Write input to the InfluxDB database if len(points) == 0: - logger.debug("Cannot export empty {} stats to InfluxDB".format(name)) + logger.debug(f"Cannot export empty {name} stats to InfluxDB") else: try: self.client.write(self.bucket, self.org, self._normalize(name, columns, points), time_precision="s") except Exception as e: # Log level set to debug instead of error (see: issue #1561) - logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e)) + logger.debug(f"Cannot export {name} stats to InfluxDB ({e})") else: - logger.debug("Export {} stats to InfluxDB".format(name)) + logger.debug(f"Export {name} stats to InfluxDB") diff --git a/glances/exports/glances_json/__init__.py b/glances/exports/glances_json/__init__.py index 62a3c204..1a2aa6df 100644 --- a/glances/exports/glances_json/__init__.py +++ b/glances/exports/glances_json/__init__.py @@ -12,7 +12,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the JSON export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # JSON file name self.json_filename = args.export_json_file @@ -21,11 +21,11 @@ class Export(GlancesExport): try: self.json_file = open(self.json_filename, 'w') self.json_file.close() - except IOError as e: - logger.critical("Cannot create the JSON file: {}".format(e)) + except OSError as e: + logger.critical(f"Cannot create the JSON file: {e}") sys.exit(2) - logger.info("Exporting stats to file: {}".format(self.json_filename)) + logger.info(f"Exporting stats to file: {self.json_filename}") self.export_enable = True @@ -34,7 +34,7 @@ class Export(GlancesExport): def exit(self): """Close the JSON file.""" - logger.debug("Finalise export interface %s" % self.export_name) + logger.debug(f"Finalise export interface {self.export_name}") self.json_file.close() def export(self, name, columns, points): @@ -44,11 +44,11 @@ class Export(GlancesExport): if name == self.last_exported_list()[0] and self.buffer != {}: # One whole loop has been completed # Flush stats to file - logger.debug("Exporting stats ({}) to JSON file ({})".format(listkeys(self.buffer), self.json_filename)) + logger.debug(f"Exporting stats ({listkeys(self.buffer)}) to JSON file ({self.json_filename})") # Export stats to JSON file with open(self.json_filename, "w") as self.json_file: - self.json_file.write("{}\n".format(json_dumps(self.buffer))) + self.json_file.write(f"{json_dumps(self.buffer)}\n") # Reset buffer self.buffer = {} diff --git a/glances/exports/glances_kafka/__init__.py b/glances/exports/glances_kafka/__init__.py index fc687e9b..783a4ad1 100644 --- a/glances/exports/glances_kafka/__init__.py +++ b/glances/exports/glances_kafka/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Kafka export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.topic = None @@ -48,7 +47,7 @@ class Export(GlancesExport): return None # Build the server URI with host and port - server_uri = '{}:{}'.format(self.host, self.port) + server_uri = f'{self.host}:{self.port}' try: s = KafkaProducer( @@ -57,16 +56,16 @@ class Export(GlancesExport): compression_type=self.compression, ) except Exception as e: - logger.critical("Cannot connect to Kafka server %s (%s)" % (server_uri, e)) + logger.critical(f"Cannot connect to Kafka server {server_uri} ({e})") sys.exit(2) else: - logger.info("Connected to the Kafka server %s" % server_uri) + logger.info(f"Connected to the Kafka server {server_uri}") return s def export(self, name, columns, points): """Write the points to the kafka server.""" - logger.debug("Export {} stats to Kafka".format(name)) + logger.debug(f"Export {name} stats to Kafka") # Create DB input data = dict(zip(columns, points)) @@ -84,7 +83,7 @@ class Export(GlancesExport): value=data, ) except Exception as e: - logger.error("Cannot export {} stats to Kafka ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to Kafka ({e})") def exit(self): """Close the Kafka export module.""" @@ -92,4 +91,4 @@ class Export(GlancesExport): self.client.flush() self.client.close() # Call the father method - super(Export, self).exit() + super().exit() diff --git a/glances/exports/glances_mongodb/__init__.py b/glances/exports/glances_mongodb/__init__.py index 953b498a..baf671cf 100644 --- a/glances/exports/glances_mongodb/__init__.py +++ b/glances/exports/glances_mongodb/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the MongoDB export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.db = None @@ -45,13 +44,13 @@ class Export(GlancesExport): if not self.export_enable: return None - server_uri = 'mongodb://%s:%s@%s:%s' % (quote_plus(self.user), quote_plus(self.password), self.host, self.port) + server_uri = f'mongodb://{quote_plus(self.user)}:{quote_plus(self.password)}@{self.host}:{self.port}' try: client = pymongo.MongoClient(server_uri) client.admin.command('ping') except Exception as e: - logger.critical("Cannot connect to MongoDB server %s:%s (%s)" % (self.host, self.port, e)) + logger.critical(f"Cannot connect to MongoDB server {self.host}:{self.port} ({e})") sys.exit(2) else: logger.info("Connected to the MongoDB server") @@ -64,7 +63,7 @@ class Export(GlancesExport): def export(self, name, columns, points): """Write the points to the MongoDB server.""" - logger.debug("Export {} stats to MongoDB".format(name)) + logger.debug(f"Export {name} stats to MongoDB") # Create DB input data = dict(zip(columns, points)) @@ -73,4 +72,4 @@ class Export(GlancesExport): try: self.database()[name].insert_one(data) except Exception as e: - logger.error("Cannot export {} stats to MongoDB ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to MongoDB ({e})") diff --git a/glances/exports/glances_mqtt/__init__.py b/glances/exports/glances_mqtt/__init__.py index 55cf8253..7aeccb03 100755 --- a/glances/exports/glances_mqtt/__init__.py +++ b/glances/exports/glances_mqtt/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -27,7 +26,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the MQTT export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.user = None @@ -87,7 +86,7 @@ class Export(GlancesExport): client.loop_start() return client except Exception as e: - logger.critical("Connection to MQTT server %s:%s failed with error: %s " % (self.host, self.port, e)) + logger.critical(f"Connection to MQTT server {self.host}:{self.port} failed with error: {e} ") return None def export(self, name, columns, points): @@ -109,7 +108,7 @@ class Export(GlancesExport): self.client.publish(topic, value) except Exception as e: - logger.error("Can not export stats to MQTT server (%s)" % e) + logger.error(f"Can not export stats to MQTT server ({e})") elif self.topic_structure == 'per-plugin': try: topic = '/'.join([self.topic, self.devicename, name]) @@ -133,4 +132,4 @@ class Export(GlancesExport): json_value = json_dumps(output_value) self.client.publish(topic, json_value) except Exception as e: - logger.error("Can not export stats to MQTT server (%s)" % e) + logger.error(f"Can not export stats to MQTT server ({e})") diff --git a/glances/exports/glances_opentsdb/__init__.py b/glances/exports/glances_opentsdb/__init__.py index 7b411499..2bfeca71 100644 --- a/glances/exports/glances_opentsdb/__init__.py +++ b/glances/exports/glances_opentsdb/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the OpenTSDB export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) # N/A @@ -52,7 +51,7 @@ class Export(GlancesExport): try: db = potsdb.Client(self.host, port=int(self.port), check_host=True) except Exception as e: - logger.critical("Cannot connect to OpenTSDB server %s:%s (%s)" % (self.host, self.port, e)) + logger.critical(f"Cannot connect to OpenTSDB server {self.host}:{self.port} ({e})") sys.exit(2) return db @@ -62,18 +61,18 @@ class Export(GlancesExport): for i in range(len(columns)): if not isinstance(points[i], Number): continue - stat_name = '{}.{}.{}'.format(self.prefix, name, columns[i]) + stat_name = f'{self.prefix}.{name}.{columns[i]}' stat_value = points[i] tags = self.parse_tags(self.tags) try: self.client.send(stat_name, stat_value, **tags) except Exception as e: - logger.error("Can not export stats %s to OpenTSDB (%s)" % (name, e)) - logger.debug("Export {} stats to OpenTSDB".format(name)) + logger.error(f"Can not export stats {name} to OpenTSDB ({e})") + logger.debug(f"Export {name} stats to OpenTSDB") def exit(self): """Close the OpenTSDB export module.""" # Waits for all outstanding metrics to be sent and background thread closes self.client.wait() # Call the father method - super(Export, self).exit() + super().exit() diff --git a/glances/exports/glances_prometheus/__init__.py b/glances/exports/glances_prometheus/__init__.py index 3a19b113..238be33b 100644 --- a/glances/exports/glances_prometheus/__init__.py +++ b/glances/exports/glances_prometheus/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Prometheus export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Load the Prometheus configuration file section self.export_enable = self.load_conf('prometheus', mandatories=['host', 'port', 'labels'], options=['prefix']) @@ -52,14 +51,14 @@ class Export(GlancesExport): try: start_http_server(port=int(self.port), addr=self.host) except Exception as e: - logger.critical("Can not start Prometheus exporter on {}:{} ({})".format(self.host, self.port, e)) + logger.critical(f"Can not start Prometheus exporter on {self.host}:{self.port} ({e})") sys.exit(2) else: - logger.info("Start Prometheus exporter on {}:{}".format(self.host, self.port)) + logger.info(f"Start Prometheus exporter on {self.host}:{self.port}") def export(self, name, columns, points): """Write the points to the Prometheus exporter using Gauge.""" - logger.debug("Export {} stats to Prometheus exporter".format(name)) + logger.debug(f"Export {name} stats to Prometheus exporter") # Remove non number stats and convert all to float (for Boolean) data = {k: float(v) for (k, v) in iteritems(dict(zip(columns, points))) if isinstance(v, Number)} diff --git a/glances/exports/glances_rabbitmq/__init__.py b/glances/exports/glances_rabbitmq/__init__.py index 5d481aa1..548e8918 100644 --- a/glances/exports/glances_rabbitmq/__init__.py +++ b/glances/exports/glances_rabbitmq/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the RabbitMQ export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.user = None @@ -69,7 +68,7 @@ class Export(GlancesExport): connection = pika.BlockingConnection(parameters) return connection.channel() except Exception as e: - logger.critical("Connection to rabbitMQ server %s:%s failed. %s" % (self.host, self.port, e)) + logger.critical(f"Connection to rabbitMQ server {self.host}:{self.port} failed. {e}") sys.exit(2) def export(self, name, columns, points): @@ -84,4 +83,4 @@ class Export(GlancesExport): try: self.client.basic_publish(exchange='', routing_key=self.queue, body=data) except Exception as e: - logger.error("Can not export stats to RabbitMQ (%s)" % e) + logger.error(f"Can not export stats to RabbitMQ ({e})") diff --git a/glances/exports/glances_restful/__init__.py b/glances/exports/glances_restful/__init__.py index 1b6ad919..8f160e1b 100644 --- a/glances/exports/glances_restful/__init__.py +++ b/glances/exports/glances_restful/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the RESTful export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.protocol = None @@ -45,15 +44,15 @@ class Export(GlancesExport): if not self.export_enable: return None # Build the RESTful URL where the stats will be posted - url = '{}://{}:{}{}'.format(self.protocol, self.host, self.port, self.path) - logger.info("Stats will be exported to the RESTful endpoint {}".format(url)) + url = f'{self.protocol}://{self.host}:{self.port}{self.path}' + logger.info(f"Stats will be exported to the RESTful endpoint {url}") return url def export(self, name, columns, points): """Export the stats to the Statsd server.""" if name == self.last_exported_list()[0] and self.buffer != {}: # One complete loop have been done - logger.debug("Export stats ({}) to RESTful endpoint ({})".format(listkeys(self.buffer), self.client)) + logger.debug(f"Export stats ({listkeys(self.buffer)}) to RESTful endpoint ({self.client})") # Export stats post(self.client, json=self.buffer, allow_redirects=True) # Reset buffer diff --git a/glances/exports/glances_riemann/__init__.py b/glances/exports/glances_riemann/__init__.py index 50e12e05..c90d74c0 100644 --- a/glances/exports/glances_riemann/__init__.py +++ b/glances/exports/glances_riemann/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -24,7 +23,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Riemann export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) # N/A @@ -50,7 +49,7 @@ class Export(GlancesExport): try: return bernhard.Client(host=self.host, port=self.port) except Exception as e: - logger.critical("Connection to Riemann failed : %s " % e) + logger.critical(f"Connection to Riemann failed : {e} ") return None def export(self, name, columns, points): @@ -64,4 +63,4 @@ class Export(GlancesExport): try: self.client.send(data) except Exception as e: - logger.error("Cannot export stats to Riemann (%s)" % e) + logger.error(f"Cannot export stats to Riemann ({e})") diff --git a/glances/exports/glances_statsd/__init__.py b/glances/exports/glances_statsd/__init__.py index 89dd3f33..88ad6b15 100644 --- a/glances/exports/glances_statsd/__init__.py +++ b/glances/exports/glances_statsd/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the Statsd export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) # N/A @@ -46,7 +45,7 @@ class Export(GlancesExport): """Init the connection to the Statsd server.""" if not self.export_enable: return None - logger.info("Stats will be exported to StatsD server: {}:{}".format(self.host, self.port)) + logger.info(f"Stats will be exported to StatsD server: {self.host}:{self.port}") return StatsClient(self.host, int(self.port), prefix=self.prefix) def export(self, name, columns, points): @@ -54,13 +53,13 @@ class Export(GlancesExport): for i in range(len(columns)): if not isinstance(points[i], Number): continue - stat_name = '{}.{}'.format(name, columns[i]) + stat_name = f'{name}.{columns[i]}' stat_value = points[i] try: self.client.gauge(normalize(stat_name), stat_value) except Exception as e: - logger.error("Can not export stats to Statsd (%s)" % e) - logger.debug("Export {} stats to Statsd".format(name)) + logger.error(f"Can not export stats to Statsd ({e})") + logger.debug(f"Export {name} stats to Statsd") def normalize(name): diff --git a/glances/exports/glances_zeromq/__init__.py b/glances/exports/glances_zeromq/__init__.py index 26c030f0..6bc2eaf5 100644 --- a/glances/exports/glances_zeromq/__init__.py +++ b/glances/exports/glances_zeromq/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -24,7 +23,7 @@ class Export(GlancesExport): def __init__(self, config=None, args=None): """Init the ZeroMQ export IF.""" - super(Export, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Mandatory configuration keys (additional to host and port) self.prefix = None @@ -46,17 +45,17 @@ class Export(GlancesExport): if not self.export_enable: return None - server_uri = 'tcp://{}:{}'.format(self.host, self.port) + server_uri = f'tcp://{self.host}:{self.port}' try: self.context = zmq.Context() publisher = self.context.socket(zmq.PUB) publisher.bind(server_uri) except Exception as e: - logger.critical("Cannot connect to ZeroMQ server %s (%s)" % (server_uri, e)) + logger.critical(f"Cannot connect to ZeroMQ server {server_uri} ({e})") sys.exit(2) else: - logger.info("Connected to the ZeroMQ server %s" % server_uri) + logger.info(f"Connected to the ZeroMQ server {server_uri}") return publisher @@ -69,7 +68,7 @@ class Export(GlancesExport): def export(self, name, columns, points): """Write the points to the ZeroMQ server.""" - logger.debug("Export {} stats to ZeroMQ".format(name)) + logger.debug(f"Export {name} stats to ZeroMQ") # Create DB input data = dict(zip(columns, points)) @@ -89,6 +88,6 @@ class Export(GlancesExport): try: self.client.send_multipart(message) except Exception as e: - logger.error("Cannot export {} stats to ZeroMQ ({})".format(name, e)) + logger.error(f"Cannot export {name} stats to ZeroMQ ({e})") return True diff --git a/glances/filter.py b/glances/filter.py index e2061277..f8ee5518 100644 --- a/glances/filter.py +++ b/glances/filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -12,7 +11,7 @@ import re from glances.logger import logger -class GlancesFilterList(object): +class GlancesFilterList: """Manage a lis of GlancesFilter objects >>> fl = GlancesFilterList() @@ -55,7 +54,7 @@ class GlancesFilterList(object): return False -class GlancesFilter(object): +class GlancesFilter: """Allow Glances to filter processes >>> f = GlancesFilter() @@ -127,9 +126,9 @@ class GlancesFilter(object): # Compute the regular expression try: self._filter_re = re.compile(self.filter) - logger.debug("Filter regex compilation OK: {}".format(self.filter)) + logger.debug(f"Filter regex compilation OK: {self.filter}") except Exception as e: - logger.error("Cannot compile filter regex: {} ({})".format(self.filter, e)) + logger.error(f"Cannot compile filter regex: {self.filter} ({e})") self._filter = None self._filter_re = None self._filter_key = None diff --git a/glances/folder_list.py b/glances/folder_list.py index 2211e5f6..67554a4a 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,14 +8,12 @@ """Manage the folder list.""" -from __future__ import unicode_literals - from glances.globals import folder_size, nativestr from glances.logger import logger from glances.timer import Timer -class FolderList(object): +class FolderList: """This class describes the optional monitored folder list. The folder list is a list of 'important' folder to monitor. diff --git a/glances/globals.py b/glances/globals.py index c0f393dc..56002c38 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -1,5 +1,4 @@ # ruff: noqa: F401 -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -145,7 +144,7 @@ def system_exec(command): try: res = subprocess.run(command.split(' '), stdout=subprocess.PIPE).stdout.decode('utf-8') except Exception as e: - res = 'ERROR: {}'.format(e) + res = f'ERROR: {e}' return res.rstrip() @@ -202,7 +201,7 @@ def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except Exception as e: - print("Admin check failed with error: %s" % e) + print(f"Admin check failed with error: {e}") traceback.print_exc() return False else: @@ -299,7 +298,7 @@ def urlopen_auth(url, username, password): return urlopen( Request( url, - headers={'Authorization': 'Basic ' + base64.b64encode(('%s:%s' % (username, password)).encode()).decode()}, + headers={'Authorization': 'Basic ' + base64.b64encode((f'{username}:{password}').encode()).decode()}, ) ) diff --git a/glances/history.py b/glances/history.py index 96d9d2de..238ba8d5 100644 --- a/glances/history.py +++ b/glances/history.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -12,7 +11,7 @@ from glances.attribute import GlancesAttribute -class GlancesHistory(object): +class GlancesHistory: """This class manage a dict of GlancesAttribute - key: stats name - value: GlancesAttribute""" diff --git a/glances/logger.py b/glances/logger.py index 67061e35..f53abab7 100644 --- a/glances/logger.py +++ b/glances/logger.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -36,7 +35,7 @@ elif os.path.isdir(_XDG_CACHE_HOME) and os.access(_XDG_CACHE_HOME, os.W_OK): safe_makedirs(os.path.join(_XDG_CACHE_HOME, 'glances')) LOG_FILENAME = os.path.join(_XDG_CACHE_HOME, 'glances', 'glances.log') else: - LOG_FILENAME = os.path.join(tempfile.gettempdir(), 'glances-{}.log'.format(getpass.getuser())) + LOG_FILENAME = os.path.join(tempfile.gettempdir(), f'glances-{getpass.getuser()}.log') # Define the logging configuration LOGGING_CFG = { @@ -88,7 +87,7 @@ def glances_logger(env_key='LOG_CFG'): user_file = os.getenv(env_key, None) if user_file and os.path.exists(user_file): # A user file as been defined. Use it... - with open(user_file, 'rt') as f: + with open(user_file) as f: config = json.load(f) # Load the configuration diff --git a/glances/main.py b/glances/main.py index dffc5f5f..b4cf05e3 100644 --- a/glances/main.py +++ b/glances/main.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ from glances.logger import LOG_FILENAME, logger from glances.processes import sort_processes_key_list -class GlancesMain(object): +class GlancesMain: """Main class to manage Glances instance.""" # Default stats' minimum refresh time is 2 seconds @@ -101,10 +100,10 @@ Examples of use: def version_msg(self): """Return the version message.""" - version = 'Glances version:\t{}\n'.format(__version__) - version += 'Glances API version:\t{}\n'.format(__apiversion__) - version += 'PsUtil version:\t\t{}\n'.format(psutil_version) - version += 'Log file:\t\t{}\n'.format(LOG_FILENAME) + version = f'Glances version:\t{__version__}\n' + version += f'Glances API version:\t{__apiversion__}\n' + version += f'PsUtil version:\t\t{psutil_version}\n' + version += f'Log file:\t\t{LOG_FILENAME}\n' return version def init_args(self): @@ -334,7 +333,7 @@ Examples of use: default=None, type=int, dest='port', - help='define the client/server TCP port [default: {}]'.format(self.server_port), + help=f'define the client/server TCP port [default: {self.server_port}]', ) parser.add_argument( '-B', @@ -374,7 +373,7 @@ Examples of use: default=self.DEFAULT_REFRESH_TIME, type=float, dest='time', - help='set minimum refresh rate in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME), + help=f'set minimum refresh rate in seconds [default: {self.DEFAULT_REFRESH_TIME} sec]', ) parser.add_argument( '-w', @@ -389,7 +388,7 @@ Examples of use: default=self.cached_time, type=int, dest='cached_time', - help='set the server cache time [default: {} sec]'.format(self.cached_time), + help=f'set the server cache time [default: {self.cached_time} sec]', ) parser.add_argument( '--stop-after', @@ -577,7 +576,7 @@ Examples of use: if args.time == self.DEFAULT_REFRESH_TIME: args.time = global_refresh - logger.debug('Global refresh rate is set to {} seconds'.format(args.time)) + logger.debug(f'Global refresh rate is set to {args.time} seconds') def init_plugins(self, args): """Init Glances plugins""" @@ -585,7 +584,7 @@ Examples of use: for s in self.config.sections(): if self.config.has_section(s) and (self.config.get_bool_value(s, 'disable', False)): disable(args, s) - logger.debug('{} disabled by the configuration file'.format(s)) + logger.debug(f'{s} disabled by the configuration file') # The configuration key can be overwrite from the command line if args and args.disable_plugin and 'all' in args.disable_plugin.split(','): if not args.enable_plugin: @@ -664,19 +663,19 @@ Examples of use: # Interactive or file password if args.server: args.password = self.__get_password( - description='Define the Glances server password ({} username): '.format(args.username), + description=f'Define the Glances server password ({args.username} username): ', confirm=True, username=args.username, ) elif args.webserver: args.password = self.__get_password( - description='Define the Glances webserver password ({} username): '.format(args.username), + description=f'Define the Glances webserver password ({args.username} username): ', confirm=True, username=args.username, ) elif args.client: args.password = self.__get_password( - description='Enter the Glances server password ({} username): '.format(args.username), + description=f'Enter the Glances server password ({args.username} username): ', clear=True, username=args.username, ) diff --git a/glances/outdated.py b/glances/outdated.py index 424e5e7e..5019e1c0 100644 --- a/glances/outdated.py +++ b/glances/outdated.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,13 +25,13 @@ try: PACKAGING_IMPORT = True except Exception as e: - logger.warning("Unable to import 'packaging' module ({}). Glances cannot check for updates.".format(e)) + logger.warning(f"Unable to import 'packaging' module ({e}). Glances cannot check for updates.") PACKAGING_IMPORT = False PYPI_API_URL = 'https://pypi.python.org/pypi/Glances/json' -class Outdated(object): +class Outdated: """ This class aims at providing methods to warn the user when a new Glances version is available on the PyPI repository (https://pypi.python.org/pypi/Glances/). @@ -56,7 +55,7 @@ class Outdated(object): if not self.args.disable_check_update: self.load_config(config) - logger.debug("Check Glances version up-to-date: {}".format(not self.args.disable_check_update)) + logger.debug(f"Check Glances version up-to-date: {not self.args.disable_check_update}") # And update ! self.get_pypi_version() @@ -68,7 +67,7 @@ class Outdated(object): if hasattr(config, 'has_section') and config.has_section(global_section): self.args.disable_check_update = config.get_value(global_section, 'check_update').lower() == 'false' else: - logger.debug("Cannot find section {} in the configuration file".format(global_section)) + logger.debug(f"Cannot find section {global_section} in the configuration file") return False return True @@ -110,9 +109,7 @@ class Outdated(object): # Check is disabled by configuration return False - logger.debug( - "Check Glances version (installed: {} / latest: {})".format(self.installed_version(), self.latest_version()) - ) + logger.debug(f"Check Glances version (installed: {self.installed_version()} / latest: {self.latest_version()})") return Version(self.latest_version()) > Version(self.installed_version()) def _load_cache(self): @@ -124,7 +121,7 @@ class Outdated(object): with open(self.cache_file, 'rb') as f: cached_data = pickle.load(f) except Exception as e: - logger.debug("Cannot read version from cache file: {} ({})".format(self.cache_file, e)) + logger.debug(f"Cannot read version from cache file: {self.cache_file} ({e})") else: logger.debug("Read version from cache file") if ( @@ -147,11 +144,11 @@ class Outdated(object): with open(self.cache_file, 'wb') as f: pickle.dump(self.data, f) except Exception as e: - logger.error("Cannot write version to cache file {} ({})".format(self.cache_file, e)) + logger.error(f"Cannot write version to cache file {self.cache_file} ({e})") def _update_pypi_version(self): """Get the latest PyPI version (as a string) via the RESTful JSON API""" - logger.debug("Get latest Glances version from the PyPI RESTful API ({})".format(PYPI_API_URL)) + logger.debug(f"Get latest Glances version from the PyPI RESTful API ({PYPI_API_URL})") # Update the current time self.data['refresh_date'] = datetime.now() @@ -159,7 +156,7 @@ class Outdated(object): try: res = urlopen(PYPI_API_URL, timeout=3).read() except (HTTPError, URLError, CertificateError) as e: - logger.debug("Cannot get Glances version from the PyPI RESTful API ({})".format(e)) + logger.debug(f"Cannot get Glances version from the PyPI RESTful API ({e})") else: self.data['latest_version'] = json.loads(nativestr(res))['info']['version'] logger.debug("Save Glances version to the cache file") diff --git a/glances/outputs/glances_bars.py b/glances/outputs/glances_bars.py index d6012b9a..abdb039e 100644 --- a/glances/outputs/glances_bars.py +++ b/glances/outputs/glances_bars.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,12 +8,10 @@ """Manage bars for Glances output.""" -from __future__ import division - from math import modf -class Bar(object): +class Bar: """Manage bar (progression or status). import sys @@ -115,7 +112,7 @@ class Bar(object): ret, '>' if self.percent > self.max_value else ' ', self.max_value, self.__unit_char ) else: - ret = '{}{:5.1f}{}'.format(ret, self.percent, self.__unit_char) + ret = f'{ret}{self.percent:5.1f}{self.__unit_char}' # Add overlay if overlay and len(overlay) < len(ret) - 6: diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 5a8321af..416bb3a2 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Curses interface class.""" -from __future__ import unicode_literals - import getpass import sys @@ -33,7 +30,7 @@ except ImportError: sys.exit(1) -class _GlancesCurses(object): +class _GlancesCurses: """This class manages the curses display (and key pressed). Note: It is a private class, use GlancesCursesClient or GlancesCursesBrowser. @@ -148,14 +145,14 @@ class _GlancesCurses(object): logger.critical("Cannot init the curses library.\n") sys.exit(1) else: - logger.debug("Curses library initialized with term: {}".format(curses.longname())) + logger.debug(f"Curses library initialized with term: {curses.longname()}") except Exception as e: if args.export: logger.info("Cannot init the curses library, quiet mode on and export.") args.quiet = True return - logger.critical("Cannot init the curses library ({})".format(e)) + logger.critical(f"Cannot init the curses library ({e})") sys.exit(1) # Load configuration file @@ -224,11 +221,11 @@ class _GlancesCurses(object): try: if hasattr(curses, 'start_color'): curses.start_color() - logger.debug('Curses interface compatible with {} colors'.format(curses.COLORS)) + logger.debug(f'Curses interface compatible with {curses.COLORS} colors') if hasattr(curses, 'use_default_colors'): curses.use_default_colors() except Exception as e: - logger.warning('Error initializing terminal color ({})'.format(e)) + logger.warning(f'Error initializing terminal color ({e})') # Init colors if self.args.disable_bold: @@ -368,7 +365,7 @@ class _GlancesCurses(object): return -1 # Actions (available in the global hotkey dict)... - logger.debug("Keypressed (code: {})".format(self.pressedkey)) + logger.debug(f"Keypressed (code: {self.pressedkey})") for hotkey in self._hotkeys: if self.pressedkey == ord(hotkey) and 'switch' in self._hotkeys[hotkey]: self._handle_switch(hotkey) @@ -495,7 +492,7 @@ class _GlancesCurses(object): if return_to_browser: logger.info("Stop Glances client and return to the browser") else: - logger.info("Stop Glances (keypressed: {})".format(self.pressedkey)) + logger.info(f"Stop Glances (keypressed: {self.pressedkey})") def _handle_refresh(self): pass @@ -716,7 +713,7 @@ class _GlancesCurses(object): # Display graph generation popup if self.args.generate_graph: if 'graph' in stats.getExportsList(): - self.display_popup('Generate graph in {}'.format(self.args.export_graph_path)) + self.display_popup(f'Generate graph in {self.args.export_graph_path}') else: logger.warning('Graph export module is disable. Run Glances with --export graph to enable it.') self.args.generate_graph = False @@ -735,7 +732,7 @@ class _GlancesCurses(object): :param process :return: None """ - logger.debug("Selected process to kill: {}".format(process)) + logger.debug(f"Selected process to kill: {process}") if 'childrens' in process: pid_to_kill = process['childrens'] @@ -755,9 +752,9 @@ class _GlancesCurses(object): try: ret_kill = glances_processes.kill(pid) except Exception as e: - logger.error('Can not kill process {} ({})'.format(pid, e)) + logger.error(f'Can not kill process {pid} ({e})') else: - logger.info('Kill signal has been sent to process {} (return code: {})'.format(pid, ret_kill)) + logger.info(f'Kill signal has been sent to process {pid} (return code: {ret_kill})') def __display_header(self, stat_display): """Display the firsts lines (header) in the Curses interface. @@ -829,7 +826,7 @@ class _GlancesCurses(object): max_width=quicklook_width, args=self.args ) except AttributeError as e: - logger.debug("Quicklook plugin not available (%s)" % e) + logger.debug(f"Quicklook plugin not available ({e})") else: plugin_widths['quicklook'] = self.get_stats_display_width(stat_display["quicklook"]) stats_width = sum(itervalues(plugin_widths)) + 1 @@ -1258,7 +1255,7 @@ class _GlancesCurses(object): ) ) except Exception as e: - logger.debug('ERROR: Can not compute plugin width ({})'.format(e)) + logger.debug(f'ERROR: Can not compute plugin width ({e})') return 0 else: return c @@ -1271,7 +1268,7 @@ class _GlancesCurses(object): try: c = [i['msg'] for i in curse_msg['msgdict']].count('\n') except Exception as e: - logger.debug('ERROR: Can not compute plugin height ({})'.format(e)) + logger.debug(f'ERROR: Can not compute plugin height ({e})') return 0 else: return c + 1 @@ -1285,21 +1282,21 @@ class GlancesCursesClient(_GlancesCurses): """Class for the Glances curse client.""" -class GlancesTextbox(Textbox, object): +class GlancesTextbox(Textbox): def __init__(self, *args, **kwargs): - super(GlancesTextbox, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def do_command(self, ch): if ch == 10: # Enter return 0 if ch == 127: # Back return 8 - return super(GlancesTextbox, self).do_command(ch) + return super().do_command(ch) -class GlancesTextboxYesNo(Textbox, object): +class GlancesTextboxYesNo(Textbox): def __init__(self, *args, **kwargs): - super(GlancesTextboxYesNo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def do_command(self, ch): - return super(GlancesTextboxYesNo, self).do_command(ch) + return super().do_command(ch) diff --git a/glances/outputs/glances_curses_browser.py b/glances/outputs/glances_curses_browser.py index f2633969..950a4349 100644 --- a/glances/outputs/glances_curses_browser.py +++ b/glances/outputs/glances_curses_browser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ class GlancesCursesBrowser(_GlancesCurses): def __init__(self, args=None): """Init the father class.""" - super(GlancesCursesBrowser, self).__init__(args=args) + super().__init__(args=args) _colors_list = { 'UNKNOWN': self.no_color, @@ -151,7 +150,7 @@ class GlancesCursesBrowser(_GlancesCurses): self.pressedkey = self.get_key(self.term_window) refresh = False if self.pressedkey != -1: - logger.debug("Key pressed. Code=%s" % self.pressedkey) + logger.debug(f"Key pressed. Code={self.pressedkey}") # Actions... if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'): @@ -163,23 +162,23 @@ class GlancesCursesBrowser(_GlancesCurses): elif self.pressedkey == 10: # 'ENTER' > Run Glances on the selected server self.active_server = self._current_page * self._page_max_lines + self.cursor_position - logger.debug("Server {}/{} selected".format(self.active_server, len(stats))) + logger.debug(f"Server {self.active_server}/{len(stats)} selected") elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65: # 'UP' > Up in the server list self.cursor_up(stats) - logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats))) + logger.debug(f"Server {self.cursor + 1}/{len(stats)} selected") elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66: # 'DOWN' > Down in the server list self.cursor_down(stats) - logger.debug("Server {}/{} selected".format(self.cursor + 1, len(stats))) + logger.debug(f"Server {self.cursor + 1}/{len(stats)} selected") elif self.pressedkey == curses.KEY_PPAGE: # 'Page UP' > Prev page in the server list self.cursor_pageup(stats) - logger.debug("PageUP: Server ({}/{}) pages.".format(self._current_page + 1, self._page_max)) + logger.debug(f"PageUP: Server ({self._current_page + 1}/{self._page_max}) pages.") elif self.pressedkey == curses.KEY_NPAGE: # 'Page Down' > Next page in the server list self.cursor_pagedown(stats) - logger.debug("PageDown: Server {}/{} pages".format(self._current_page + 1, self._page_max)) + logger.debug(f"PageDown: Server {self._current_page + 1}/{self._page_max} pages") elif self.pressedkey == ord('1'): self._stats_list = None refresh = True @@ -211,7 +210,7 @@ class GlancesCursesBrowser(_GlancesCurses): :param return_to_browser: """ # Flush display - logger.debug('Servers list: {}'.format(stats)) + logger.debug(f'Servers list: {stats}') self.flush(stats) # Wait @@ -268,19 +267,19 @@ class GlancesCursesBrowser(_GlancesCurses): elif len(stats) == 1: msg = 'One Glances server available' else: - msg = '{} Glances servers available'.format(stats_len) + msg = f'{stats_len} Glances servers available' if self.args.disable_autodiscover: msg += ' (auto discover is disabled)' if screen_y > 1: self.term_window.addnstr(y, x, msg, screen_x - x, self.colors_list['TITLE']) - msg = '{}'.format(self._get_status_count(stats)) + msg = f'{self._get_status_count(stats)}' self.term_window.addnstr(y + 1, x, msg, screen_x - x) if stats_len > stats_max and screen_y > 2: - msg = '{} servers displayed.({}/{}) {}'.format( - self.get_pagelines(stats), self._current_page + 1, self._page_max, self._get_status_count(stats) - ) + page_lines = self.get_pagelines(stats) + status_count = self._get_status_count(stats) + msg = f'{page_lines} servers displayed.({self._current_page + 1}/{self._page_max}) {status_count}' self.term_window.addnstr(y + 1, x, msg, screen_x - x) if stats_len == 0: @@ -335,7 +334,7 @@ class GlancesCursesBrowser(_GlancesCurses): try: server_stat[c[0]] = v[c[0]] except KeyError as e: - logger.debug("Cannot grab stats {} from server (KeyError: {})".format(c[0], e)) + logger.debug(f"Cannot grab stats {c[0]} from server (KeyError: {e})") server_stat[c[0]] = '?' # Display alias instead of name try: diff --git a/glances/outputs/glances_restful_api.py b/glances/outputs/glances_restful_api.py index 8ef876a0..59647a39 100644 --- a/glances/outputs/glances_restful_api.py +++ b/glances/outputs/glances_restful_api.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -13,7 +12,6 @@ import os import sys import tempfile import webbrowser -from io import open from urllib.parse import urljoin try: @@ -46,6 +44,7 @@ try: except ImportError: logger.critical('Uvicorn import error. Glances cannot start in web server mode.') sys.exit(2) +import builtins import contextlib import threading import time @@ -77,7 +76,7 @@ class GlancesUvicornServer(uvicorn.Server): thread.join() -class GlancesRestfulApi(object): +class GlancesRestfulApi: """This class manages the Restful API server.""" API_VERSION = __apiversion__ @@ -102,7 +101,7 @@ class GlancesRestfulApi(object): self.load_config(config) # Set the bind URL - self.bind_url = urljoin('http://{}:{}/'.format(self.args.bind_address, self.args.port), self.url_prefix) + self.bind_url = urljoin(f'http://{self.args.bind_address}:{self.args.port}/', self.url_prefix) # FastAPI Init if self.args.password: @@ -151,9 +150,9 @@ class GlancesRestfulApi(object): self.url_prefix = '/' if config is not None and config.has_section('outputs'): n = config.get_value('outputs', 'max_processes_display', default=None) - logger.debug('Number of processes to display in the WebUI: {}'.format(n)) + logger.debug(f'Number of processes to display in the WebUI: {n}') self.url_prefix = config.get_value('outputs', 'url_prefix', default='/') - logger.debug('URL prefix: {}'.format(self.url_prefix)) + logger.debug(f'URL prefix: {self.url_prefix}') def __update__(self): # Never update more than 1 time per cached_time @@ -184,92 +183,92 @@ class GlancesRestfulApi(object): # REST API router.add_api_route( - '/api/%s/status' % self.API_VERSION, + f'/api/{self.API_VERSION}/status', status_code=status.HTTP_200_OK, response_class=ORJSONResponse, endpoint=self._api_status, ) router.add_api_route( - '/api/%s/config' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_config + f'/api/{self.API_VERSION}/config', response_class=ORJSONResponse, endpoint=self._api_config ) router.add_api_route( - '/api/%s/config/{section}' % self.API_VERSION, + f'/api/{self.API_VERSION}/config/{{section}}', response_class=ORJSONResponse, endpoint=self._api_config_section, ) router.add_api_route( - '/api/%s/config/{section}/{item}' % self.API_VERSION, + f'/api/{self.API_VERSION}/config/{{section}}/{{item}}', response_class=ORJSONResponse, endpoint=self._api_config_section_item, ) - router.add_api_route('/api/%s/args' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_args) + router.add_api_route(f'/api/{self.API_VERSION}/args', response_class=ORJSONResponse, endpoint=self._api_args) router.add_api_route( - '/api/%s/args/{item}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_args_item + f'/api/{self.API_VERSION}/args/{{item}}', response_class=ORJSONResponse, endpoint=self._api_args_item ) router.add_api_route( - '/api/%s/pluginslist' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_plugins + f'/api/{self.API_VERSION}/pluginslist', response_class=ORJSONResponse, endpoint=self._api_plugins ) - router.add_api_route('/api/%s/all' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all) + router.add_api_route(f'/api/{self.API_VERSION}/all', response_class=ORJSONResponse, endpoint=self._api_all) router.add_api_route( - '/api/%s/all/limits' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all_limits + f'/api/{self.API_VERSION}/all/limits', response_class=ORJSONResponse, endpoint=self._api_all_limits ) router.add_api_route( - '/api/%s/all/views' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_all_views + f'/api/{self.API_VERSION}/all/views', response_class=ORJSONResponse, endpoint=self._api_all_views ) - router.add_api_route('/api/%s/help' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_help) - router.add_api_route('/api/%s/{plugin}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api) + router.add_api_route(f'/api/{self.API_VERSION}/help', response_class=ORJSONResponse, endpoint=self._api_help) + router.add_api_route(f'/api/{self.API_VERSION}/{{plugin}}', response_class=ORJSONResponse, endpoint=self._api) router.add_api_route( - '/api/%s/{plugin}/history' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_history + f'/api/{self.API_VERSION}/{{plugin}}/history', response_class=ORJSONResponse, endpoint=self._api_history ) router.add_api_route( - '/api/%s/{plugin}/history/{nb}' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/history/{{nb}}', response_class=ORJSONResponse, endpoint=self._api_history, ) router.add_api_route( - '/api/%s/{plugin}/top/{nb}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_top + f'/api/{self.API_VERSION}/{{plugin}}/top/{{nb}}', response_class=ORJSONResponse, endpoint=self._api_top ) router.add_api_route( - '/api/%s/{plugin}/limits' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_limits + f'/api/{self.API_VERSION}/{{plugin}}/limits', response_class=ORJSONResponse, endpoint=self._api_limits ) router.add_api_route( - '/api/%s/{plugin}/views' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_views + f'/api/{self.API_VERSION}/{{plugin}}/views', response_class=ORJSONResponse, endpoint=self._api_views ) router.add_api_route( - '/api/%s/{plugin}/{item}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_item + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}', response_class=ORJSONResponse, endpoint=self._api_item ) router.add_api_route( - '/api/%s/{plugin}/{item}/history' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/history', response_class=ORJSONResponse, endpoint=self._api_item_history, ) router.add_api_route( - '/api/%s/{plugin}/{item}/history/{nb}' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/history/{{nb}}', response_class=ORJSONResponse, endpoint=self._api_item_history, ) router.add_api_route( - '/api/%s/{plugin}/{item}/description' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/description', response_class=ORJSONResponse, endpoint=self._api_item_description, ) router.add_api_route( - '/api/%s/{plugin}/{item}/unit' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/unit', response_class=ORJSONResponse, endpoint=self._api_item_unit, ) router.add_api_route( - '/api/%s/{plugin}/{item}/{value}' % self.API_VERSION, + f'/api/{self.API_VERSION}/{{plugin}}/{{item}}/{{value}}', response_class=ORJSONResponse, endpoint=self._api_value, ) # Restful API - bindmsg = 'Glances RESTful API Server started on {}api/{}'.format(self.bind_url, self.API_VERSION) + bindmsg = f'Glances RESTful API Server started on {self.bind_url}api/{self.API_VERSION}' logger.info(bindmsg) # WEB UI @@ -280,9 +279,9 @@ class GlancesRestfulApi(object): # Statics files self._app.mount("/static", StaticFiles(directory=self.STATIC_PATH), name="static") - logger.info("Get WebUI in {}".format(self.STATIC_PATH)) + logger.info(f"Get WebUI in {self.STATIC_PATH}") - bindmsg = 'Glances Web User Interface started on {}'.format(self.bind_url) + bindmsg = f'Glances Web User Interface started on {self.bind_url}' else: bindmsg = 'The WebUI is disable (--disable-webui)' @@ -317,7 +316,7 @@ class GlancesRestfulApi(object): try: self.uvicorn_server = GlancesUvicornServer(config=uvicorn_config) except Exception as e: - logger.critical('Error: Can not ran Glances Web server ({})'.format(e)) + logger.critical(f'Error: Can not ran Glances Web server ({e})') self.uvicorn_server = None else: with self.uvicorn_server.run_in_thread(): @@ -369,7 +368,7 @@ class GlancesRestfulApi(object): try: plist = self.stats.get_plugin("help").get_view_data() except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get help view data (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get help view data ({str(e)})") return ORJSONResponse(plist) @@ -405,7 +404,7 @@ class GlancesRestfulApi(object): try: plist = self.plugins_list except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin list (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin list ({str(e)})") return ORJSONResponse(plist) @@ -420,10 +419,10 @@ class GlancesRestfulApi(object): if self.args.debug: fname = os.path.join(tempfile.gettempdir(), 'glances-debug.json') try: - with open(fname) as f: + with builtins.open(fname) as f: return f.read() - except IOError: - logger.debug("Debug file (%s) not found" % fname) + except OSError: + logger.debug(f"Debug file ({fname}) not found") # Update the stat self.__update__() @@ -432,7 +431,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the stat ID statval = self.stats.getAllAsDict() except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get stats (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get stats ({str(e)})") return ORJSONResponse(statval) @@ -448,7 +447,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the stat limits limits = self.stats.getAllLimitsAsDict() except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get limits (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get limits ({str(e)})") return ORJSONResponse(limits) @@ -464,7 +463,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the stat view limits = self.stats.getAllViewsAsDict() except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get views (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get views ({str(e)})") return ORJSONResponse(limits) @@ -479,7 +478,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -489,9 +488,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the stat ID statval = self.stats.get_plugin(plugin).get_raw() except Exception as e: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e)) - ) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin {plugin} ({str(e)})") return ORJSONResponse(statval) @@ -508,7 +505,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -518,9 +515,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the stat ID statval = self.stats.get_plugin(plugin).get_raw() except Exception as e: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e)) - ) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin {plugin} ({str(e)})") print(statval) @@ -541,7 +536,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -552,7 +547,7 @@ class GlancesRestfulApi(object): statval = self.stats.get_plugin(plugin).get_raw_history(nb=int(nb)) except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin history %s (%s)" % (plugin, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get plugin history {plugin} ({str(e)})" ) return statval @@ -568,7 +563,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) try: @@ -576,7 +571,7 @@ class GlancesRestfulApi(object): ret = self.stats.get_plugin(plugin).limits except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get limits for plugin %s (%s)" % (plugin, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get limits for plugin {plugin} ({str(e)})" ) return ORJSONResponse(ret) @@ -592,7 +587,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) try: @@ -600,7 +595,7 @@ class GlancesRestfulApi(object): ret = self.stats.get_plugin(plugin).get_views() except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get views for plugin %s (%s)" % (plugin, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get views for plugin {plugin} ({str(e)})" ) return ORJSONResponse(ret) @@ -616,7 +611,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -628,7 +623,7 @@ class GlancesRestfulApi(object): except Exception as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get item %s in plugin %s (%s)" % (item, plugin, str(e)), + detail=f"Cannot get item {item} in plugin {plugin} ({str(e)})", ) return ORJSONResponse(ret) @@ -645,7 +640,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -656,7 +651,7 @@ class GlancesRestfulApi(object): ret = self.stats.get_plugin(plugin).get_raw_history(item, nb=nb) except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get history for plugin %s (%s)" % (plugin, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get history for plugin {plugin} ({str(e)})" ) else: return ORJSONResponse(ret) @@ -672,7 +667,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) try: @@ -681,7 +676,7 @@ class GlancesRestfulApi(object): except Exception as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get %s description for plugin %s (%s)" % (item, plugin, str(e)), + detail=f"Cannot get {item} description for plugin {plugin} ({str(e)})", ) else: return ORJSONResponse(ret) @@ -697,7 +692,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) try: @@ -706,7 +701,7 @@ class GlancesRestfulApi(object): except Exception as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get %s unit for plugin %s (%s)" % (item, plugin, str(e)), + detail=f"Cannot get {item} unit for plugin {plugin} ({str(e)})", ) else: return ORJSONResponse(ret) @@ -722,7 +717,7 @@ class GlancesRestfulApi(object): if plugin not in self.plugins_list: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + detail=f"Unknown plugin {plugin} (available plugins: {self.plugins_list})", ) # Update the stat @@ -734,7 +729,7 @@ class GlancesRestfulApi(object): except Exception as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get %s = %s for plugin %s (%s)" % (item, value, plugin, str(e)), + detail=f"Cannot get {item} = {value} for plugin {plugin} ({str(e)})", ) else: return ORJSONResponse(ret) @@ -750,7 +745,7 @@ class GlancesRestfulApi(object): # Get the RAW value of the config' dict args_json = self.config.as_dict() except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config ({str(e)})") else: return ORJSONResponse(args_json) @@ -764,16 +759,14 @@ class GlancesRestfulApi(object): """ config_dict = self.config.as_dict() if section not in config_dict: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % section - ) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown configuration item {section}") try: # Get the RAW value of the config' dict ret_section = config_dict[section] except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config section %s (%s)" % (section, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config section {section} ({str(e)})" ) return ORJSONResponse(ret_section) @@ -788,16 +781,14 @@ class GlancesRestfulApi(object): """ config_dict = self.config.as_dict() if section not in config_dict: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % section - ) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown configuration item {section}") try: # Get the RAW value of the config' dict section ret_section = config_dict[section] except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get config section %s (%s)" % (section, str(e)) + status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get config section {section} ({str(e)})" ) try: @@ -806,7 +797,7 @@ class GlancesRestfulApi(object): except Exception as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get item %s in config section %s (%s)" % (item, section, str(e)), + detail=f"Cannot get item {item} in config section {section} ({str(e)})", ) return ORJSONResponse(ret_item) @@ -824,7 +815,7 @@ class GlancesRestfulApi(object): # Source: https://docs.python.org/%s/library/functions.html#vars args_json = vars(self.args) except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get args (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get args ({str(e)})") return ORJSONResponse(args_json) @@ -837,7 +828,7 @@ class GlancesRestfulApi(object): HTTP/404 if others error """ if item not in self.args: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown argument item %s" % item) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Unknown argument item {item}") try: # Get the RAW value of the args' dict @@ -845,6 +836,6 @@ class GlancesRestfulApi(object): # Source: https://docs.python.org/%s/library/functions.html#vars args_json = vars(self.args)[item] except Exception as e: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get args item (%s)" % str(e)) + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Cannot get args item ({str(e)})") return ORJSONResponse(args_json) diff --git a/glances/outputs/glances_sparklines.py b/glances/outputs/glances_sparklines.py index 99f6e9fe..b78d40b0 100644 --- a/glances/outputs/glances_sparklines.py +++ b/glances/outputs/glances_sparklines.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Manage sparklines for Glances output.""" -from __future__ import division, unicode_literals - import sys from glances.globals import nativestr @@ -21,17 +18,17 @@ sparklines_module = True try: from sparklines import sparklines except ImportError as e: - logger.warning("Sparklines module not found ({})".format(e)) + logger.warning(f"Sparklines module not found ({e})") sparklines_module = False try: '┌┬┐╔╦╗╒╤╕╓╥╖│║─═├┼┤╠╬╣╞╪╡╟╫╢└┴┘╚╩╝╘╧╛╙╨╜'.encode(sys.stdout.encoding) except (UnicodeEncodeError, TypeError) as e: - logger.warning("UTF-8 is mandatory for sparklines ({})".format(e)) + logger.warning(f"UTF-8 is mandatory for sparklines ({e})") sparklines_module = False -class Sparkline(object): +class Sparkline: """Manage sparklines (see https://pypi.org/project/sparklines/).""" def __init__(self, size, pre_char='[', post_char=']', unit_char='%', display_value=True): @@ -83,7 +80,7 @@ class Sparkline(object): if self.__display_value: percents_without_none = [x for x in self.percents if x is not None] if len(percents_without_none) > 0: - ret = '{}{:5.1f}{}'.format(ret, percents_without_none[-1], self.__unit_char) + ret = f'{ret}{percents_without_none[-1]:5.1f}{self.__unit_char}' ret = nativestr(ret) if overwrite and len(overwrite) < len(ret) - 6: ret = overwrite + ret[len(overwrite) :] diff --git a/glances/outputs/glances_stdout.py b/glances/outputs/glances_stdout.py index 817c911b..e6e7aec7 100644 --- a/glances/outputs/glances_stdout.py +++ b/glances/outputs/glances_stdout.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -15,7 +14,7 @@ from glances.globals import printandflush from glances.logger import logger -class GlancesStdout(object): +class GlancesStdout: """This class manages the Stdout display.""" def __init__(self, config=None, args=None): @@ -65,9 +64,9 @@ class GlancesStdout(object): # With attribute if isinstance(stat, dict): try: - printandflush("{}.{}: {}".format(plugin, attribute, stat[attribute])) + printandflush(f"{plugin}.{attribute}: {stat[attribute]}") except KeyError as err: - logger.error("Can not display stat {}.{} ({})".format(plugin, attribute, err)) + logger.error(f"Can not display stat {plugin}.{attribute} ({err})") elif isinstance(stat, list): for i in stat: if key is None: @@ -77,12 +76,12 @@ class GlancesStdout(object): else: continue try: - printandflush("{}.{}.{}: {}".format(plugin, i_key, attribute, i[attribute])) + printandflush(f"{plugin}.{i_key}.{attribute}: {i[attribute]}") except KeyError as err: - logger.error("Can not display stat {}.{} ({})".format(plugin, attribute, err)) + logger.error(f"Can not display stat {plugin}.{attribute} ({err})") else: # Without attribute - printandflush("{}: {}".format(plugin, stat)) + printandflush(f"{plugin}: {stat}") # Wait until next refresh if duration > 0: diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 8b9350d9..f152b903 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -17,15 +16,15 @@ from glances import __apiversion__ from glances.globals import iteritems from glances.logger import logger -API_URL = "http://localhost:61208/api/{api_version}".format(api_version=__apiversion__) +API_URL = f"http://localhost:61208/api/{__apiversion__}" -APIDOC_HEADER = """\ +APIDOC_HEADER = f"""\ .. _api: API (Restfull/JSON) documentation ================================= -This documentation describes the Glances API version {api_version} (Restfull/JSON) interface. +This documentation describes the Glances API version {__apiversion__} (Restfull/JSON) interface. For Glances version 3, please have a look on: ``https://github.com/nicolargo/glances/blob/support/glancesv3/docs/api.rst`` @@ -44,7 +43,7 @@ It is also ran automatically when Glances is started in Web server mode (-w). API URL ------- -The default root API URL is ``http://localhost:61208/api/{api_version}``. +The default root API URL is ``http://localhost:61208/api/{__apiversion__}``. The bind address and port could be changed using the ``--bind`` and ``--port`` command line options. @@ -59,7 +58,7 @@ For example: [outputs] url_prefix = /glances/ -will change the root API URL to ``http://localhost:61208/glances/api/{api_version}`` and the Web UI URL to +will change the root API URL to ``http://localhost:61208/glances/api/{__apiversion__}`` and the Web UI URL to ``http://localhost:61208/glances/`` API documentation URL @@ -74,7 +73,7 @@ WebUI refresh It is possible to change the Web UI refresh rate (default is 2 seconds) using the following option in the URL: ``http://localhost:61208/glances/?refresh=5`` -""".format(api_version=__apiversion__) +""" def indent_stat(stat, indent=' '): @@ -95,7 +94,7 @@ def print_api_status(): print('') print('Get the Rest API status::') print('') - print(' # curl -I {}/status'.format(API_URL)) + print(f' # curl -I {API_URL}/status') print(indent_stat('HTTP/1.0 200 OK')) print('') @@ -107,20 +106,20 @@ def print_plugins_list(stat): print('') print('Get the plugins list::') print('') - print(' # curl {}/pluginslist'.format(API_URL)) + print(f' # curl {API_URL}/pluginslist') print(indent_stat(stat)) print('') def print_plugin_stats(plugin, stat): - sub_title = 'GET {}'.format(plugin) + sub_title = f'GET {plugin}' print(sub_title) print('-' * len(sub_title)) print('') print('Get plugin stats::') print('') - print(' # curl {}/{}'.format(API_URL, plugin)) + print(f' # curl {API_URL}/{plugin}') print(indent_stat(json.loads(stat.get_stats()))) print('') @@ -179,7 +178,7 @@ def print_plugin_description(plugin, stat): print('') else: - logger.error('No fields_description variable defined for plugin {}'.format(plugin)) + logger.error(f'No fields_description variable defined for plugin {plugin}') def print_plugin_item_value(plugin, stat, stat_export): @@ -201,13 +200,13 @@ def print_plugin_item_value(plugin, stat, stat_export): value = stat_item[item] print('Get a specific field::') print('') - print(' # curl {}/{}/{}'.format(API_URL, plugin, item)) + print(f' # curl {API_URL}/{plugin}/{item}') print(indent_stat(stat_item)) print('') if item and value and stat.get_stats_value(item, value): print('Get a specific item when field matches the given value::') print('') - print(' # curl {}/{}/{}/{}'.format(API_URL, plugin, item, value)) + print(f' # curl {API_URL}/{plugin}/{item}/{value}') print(indent_stat(json.loads(stat.get_stats_value(item, value)))) print('') @@ -219,7 +218,7 @@ def print_all(): print('') print('Get all Glances stats::') print('') - print(' # curl {}/all'.format(API_URL)) + print(f' # curl {API_URL}/all') print(' Return a very big dictionary (avoid using this request, performances will be poor)...') print('') @@ -233,7 +232,7 @@ def print_top(stats): print('') print('Get top 2 processes of the processlist plugin::') print('') - print(' # curl {}/processlist/top/2'.format(API_URL)) + print(f' # curl {API_URL}/processlist/top/2') print(indent_stat(stats.get_plugin('processlist').get_export()[:2])) print('') print('Note: Only work for plugin with a list of items') @@ -246,7 +245,7 @@ def print_fields_info(stats): print('-' * len(sub_title)) print('Get item description (human readable) for a specific plugin/item::') print('') - print(' # curl {}/diskio/read_bytes/description'.format(API_URL)) + print(f' # curl {API_URL}/diskio/read_bytes/description') print(indent_stat(stats.get_plugin('diskio').get_item_info('read_bytes', 'description'))) print('') print('Note: the description is defined in the fields_description variable of the plugin.') @@ -256,7 +255,7 @@ def print_fields_info(stats): print('-' * len(sub_title)) print('Get item unit for a specific plugin/item::') print('') - print(' # curl {}/diskio/read_bytes/unit'.format(API_URL)) + print(f' # curl {API_URL}/diskio/read_bytes/unit') print(indent_stat(stats.get_plugin('diskio').get_item_info('read_bytes', 'unit'))) print('') print('Note: the description is defined in the fields_description variable of the plugin.') @@ -274,22 +273,22 @@ def print_history(stats): print('') print('History of a plugin::') print('') - print(' # curl {}/cpu/history'.format(API_URL)) + print(f' # curl {API_URL}/cpu/history') print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=3)))) print('') print('Limit history to last 2 values::') print('') - print(' # curl {}/cpu/history/2'.format(API_URL)) + print(f' # curl {API_URL}/cpu/history/2') print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=2)))) print('') print('History for a specific field::') print('') - print(' # curl {}/cpu/system/history'.format(API_URL)) + print(f' # curl {API_URL}/cpu/system/history') print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system')))) print('') print('Limit history for a specific field to last 2 values::') print('') - print(' # curl {}/cpu/system/history'.format(API_URL)) + print(f' # curl {API_URL}/cpu/system/history') print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system', nb=2)))) print('') @@ -301,17 +300,17 @@ def print_limits(stats): print('') print('All limits/thresholds::') print('') - print(' # curl {}/all/limits'.format(API_URL)) + print(f' # curl {API_URL}/all/limits') print(indent_stat(stats.getAllLimitsAsDict())) print('') print('Limits/thresholds for the cpu plugin::') print('') - print(' # curl {}/cpu/limits'.format(API_URL)) + print(f' # curl {API_URL}/cpu/limits') print(indent_stat(stats.get_plugin('cpu').limits)) print('') -class GlancesStdoutApiDoc(object): +class GlancesStdoutApiDoc: """This class manages the fields description display.""" def __init__(self, config=None, args=None): diff --git a/glances/outputs/glances_stdout_csv.py b/glances/outputs/glances_stdout_csv.py index 53f8c12d..1fa3b7b1 100644 --- a/glances/outputs/glances_stdout_csv.py +++ b/glances/outputs/glances_stdout_csv.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -14,7 +13,7 @@ import time from glances.globals import printandflush -class GlancesStdoutCsv(object): +class GlancesStdoutCsv: """This class manages the StdoutCsv display.""" separator = ',' @@ -53,18 +52,18 @@ class GlancesStdoutCsv(object): line = '' if attribute is not None: - line += '{}.{}{}'.format(plugin, attribute, self.separator) + line += f'{plugin}.{attribute}{self.separator}' else: if isinstance(stat, dict): for k in stat.keys(): - line += '{}.{}{}'.format(plugin, str(k), self.separator) + line += f'{plugin}.{str(k)}{self.separator}' elif isinstance(stat, list): for i in stat: if isinstance(i, dict) and 'key' in i: for k in i.keys(): line += '{}.{}.{}{}'.format(plugin, str(i[i['key']]), str(k), self.separator) else: - line += '{}{}'.format(plugin, self.separator) + line += f'{plugin}{self.separator}' return line @@ -73,18 +72,18 @@ class GlancesStdoutCsv(object): line = '' if attribute is not None: - line += '{}{}'.format(str(stat.get(attribute, self.na)), self.separator) + line += f'{str(stat.get(attribute, self.na))}{self.separator}' else: if isinstance(stat, dict): for v in stat.values(): - line += '{}{}'.format(str(v), self.separator) + line += f'{str(v)}{self.separator}' elif isinstance(stat, list): for i in stat: if isinstance(i, dict) and 'key' in i: for v in i.values(): - line += '{}{}'.format(str(v), self.separator) + line += f'{str(v)}{self.separator}' else: - line += '{}{}'.format(str(stat), self.separator) + line += f'{str(stat)}{self.separator}' return line diff --git a/glances/outputs/glances_stdout_issue.py b/glances/outputs/glances_stdout_issue.py index 55e2cd41..b6f50edb 100644 --- a/glances/outputs/glances_stdout_issue.py +++ b/glances/outputs/glances_stdout_issue.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -39,7 +38,7 @@ class colors: self.NO = '' -class GlancesStdoutIssue(object): +class GlancesStdoutIssue: """This class manages the Issue display.""" def __init__(self, config=None, args=None): @@ -52,18 +51,14 @@ class GlancesStdoutIssue(object): def print_version(self): sys.stdout.write('=' * TERMINAL_WIDTH + '\n') - sys.stdout.write( - 'Glances {} ({})\n'.format(colors.BLUE + __version__ + colors.NO, os.path.realpath(glances.__file__)) - ) - sys.stdout.write('Python {} ({})\n'.format(colors.BLUE + platform.python_version() + colors.NO, sys.executable)) - sys.stdout.write( - 'PsUtil {} ({})\n'.format(colors.BLUE + psutil_version + colors.NO, os.path.realpath(psutil.__file__)) - ) + sys.stdout.write(f'Glances {colors.BLUE + __version__ + colors.NO} ({os.path.realpath(glances.__file__)})\n') + sys.stdout.write(f'Python {colors.BLUE + platform.python_version() + colors.NO} ({sys.executable})\n') + sys.stdout.write(f'PsUtil {colors.BLUE + psutil_version + colors.NO} ({os.path.realpath(psutil.__file__)})\n') sys.stdout.write('=' * TERMINAL_WIDTH + '\n') sys.stdout.flush() def print_issue(self, plugin, result, message): - sys.stdout.write('{}{}{}'.format(colors.BLUE + plugin, result, message)) + sys.stdout.write(f'{colors.BLUE + plugin}{result}{message}') sys.stdout.write(colors.NO + '\n') sys.stdout.flush() @@ -108,9 +103,7 @@ class GlancesStdoutIssue(object): except Exception as e: stat_error = e if stat_error is None: - result = (colors.GREEN + '[OK] ' + colors.BLUE + ' {:.5f}s '.format(counter.get())).rjust( - 41 - len(plugin) - ) + result = (colors.GREEN + '[OK] ' + colors.BLUE + f' {counter.get():.5f}s ').rjust(41 - len(plugin)) if isinstance(stat, list) and len(stat) > 0 and 'key' in stat[0]: key = 'key={} '.format(stat[0]['key']) stat_output = pprint.pformat([stat[0]], compact=True, width=120, depth=3) @@ -118,9 +111,7 @@ class GlancesStdoutIssue(object): else: message = '\n' + colors.NO + pprint.pformat(stat, compact=True, width=120, depth=2) else: - result = (colors.RED + '[ERROR]' + colors.BLUE + ' {:.5f}s '.format(counter.get())).rjust( - 41 - len(plugin) - ) + result = (colors.RED + '[ERROR]' + colors.BLUE + f' {counter.get():.5f}s ').rjust(41 - len(plugin)) message = colors.NO + str(stat_error)[0 : TERMINAL_WIDTH - 41] # Display the result @@ -128,7 +119,7 @@ class GlancesStdoutIssue(object): # Display total time need to update all plugins sys.stdout.write('=' * TERMINAL_WIDTH + '\n') - print("Total time to update all stats: {}{:.5f}s{}".format(colors.BLUE, counter_total.get(), colors.NO)) + print(f"Total time to update all stats: {colors.BLUE}{counter_total.get():.5f}s{colors.NO}") sys.stdout.write('=' * TERMINAL_WIDTH + '\n') # Return True to exit directly (no refresh) diff --git a/glances/outputs/glances_stdout_json.py b/glances/outputs/glances_stdout_json.py index dbb10e96..d3c1a019 100644 --- a/glances/outputs/glances_stdout_json.py +++ b/glances/outputs/glances_stdout_json.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -14,7 +13,7 @@ import time from glances.globals import printandflush -class GlancesStdoutJson(object): +class GlancesStdoutJson: """This class manages the Stdout JSON display.""" def __init__(self, config=None, args=None): @@ -47,7 +46,7 @@ class GlancesStdoutJson(object): else: continue # Display stats - printandflush('{}: {}'.format(plugin, stat)) + printandflush(f'{plugin}: {stat}') # Wait until next refresh if duration > 0: diff --git a/glances/outputs/glances_unicode.py b/glances/outputs/glances_unicode.py index 99f4e786..33c43764 100644 --- a/glances/outputs/glances_unicode.py +++ b/glances/outputs/glances_unicode.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # diff --git a/glances/password.py b/glances/password.py index 9d79e995..fdaea71a 100644 --- a/glances/password.py +++ b/glances/password.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,19 +8,19 @@ """Manage password.""" +import builtins import getpass import hashlib import os import sys import uuid -from io import open from glances.config import user_config_dir from glances.globals import b, safe_makedirs, weak_lru_cache from glances.logger import logger -class GlancesPassword(object): +class GlancesPassword: """This class contains all the methods relating to password.""" def __init__(self, username='glances', config=None): @@ -77,7 +76,7 @@ class GlancesPassword(object): """ if os.path.exists(self.password_file) and not clear: # If the password file exist then use it - logger.info("Read password from file {}".format(self.password_file)) + logger.info(f"Read password from file {self.password_file}") password = self.load_password() else: # password_hash is the plain SHA-pbkdf2_hmac password @@ -112,11 +111,11 @@ class GlancesPassword(object): safe_makedirs(self.password_dir) # Create/overwrite the password file - with open(self.password_file, 'wb') as file_pwd: + with builtins.open(self.password_file, 'wb') as file_pwd: file_pwd.write(b(hashed_password)) def load_password(self): """Load the hashed password from the Glances folder.""" # Read the password file, if it exists - with open(self.password_file, 'r') as file_pwd: + with builtins.open(self.password_file) as file_pwd: return file_pwd.read() diff --git a/glances/password_list.py b/glances/password_list.py index 1f3973fa..5b8fa078 100644 --- a/glances/password_list.py +++ b/glances/password_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -19,7 +18,7 @@ class GlancesPasswordList(GlancesPassword): _section = "passwords" def __init__(self, config=None, args=None): - super(GlancesPasswordList, self).__init__() + super().__init__() # password_dict is a dict (JSON compliant) # {'host': 'password', ... } # Load the configuration file @@ -32,14 +31,14 @@ class GlancesPasswordList(GlancesPassword): if config is None: logger.warning("No configuration file available. Cannot load password list.") elif not config.has_section(self._section): - logger.warning("No [%s] section in the configuration file. Cannot load password list." % self._section) + logger.warning(f"No [{self._section}] section in the configuration file. Cannot load password list.") else: - logger.info("Start reading the [%s] section in the configuration file" % self._section) + logger.info(f"Start reading the [{self._section}] section in the configuration file") password_dict = dict(config.items(self._section)) # Password list loaded - logger.info("%s password(s) loaded from the configuration file" % len(password_dict)) + logger.info(f"{len(password_dict)} password(s) loaded from the configuration file") return password_dict diff --git a/glances/plugins/alert/__init__.py b/glances/plugins/alert/__init__.py index 4068d395..5350ba24 100644 --- a/glances/plugins/alert/__init__.py +++ b/glances/plugins/alert/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -101,9 +100,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True @@ -174,7 +171,7 @@ class PluginModel(GlancesPluginModel): # Top processes top_process = ', '.join(alert['top']) if top_process != '': - msg = ': {}'.format(top_process) + msg = f': {top_process}' ret.append(self.curse_add_line(msg)) return ret diff --git a/glances/plugins/amps/__init__.py b/glances/plugins/amps/__init__.py index acdcf315..387a675d 100644 --- a/glances/plugins/amps/__init__.py +++ b/glances/plugins/amps/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -35,9 +34,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) self.args = args self.config = config @@ -119,10 +116,10 @@ class PluginModel(GlancesPluginModel): second_column = '{}'.format(m['count'] if m['regex'] else '') for line in m['result'].split('\n'): # Display first column with the process name... - msg = '{:<16} '.format(first_column) + msg = f'{first_column:<16} ' ret.append(self.curse_add_line(msg, first_column_style)) # ... and second column with the number of matching processes... - msg = '{:<4} '.format(second_column) + msg = f'{second_column:<4} ' ret.append(self.curse_add_line(msg)) # ... only on the first line first_column = second_column = '' diff --git a/glances/plugins/cloud/__init__.py b/glances/plugins/cloud/__init__.py index bb9880f8..1203d9c7 100644 --- a/glances/plugins/cloud/__init__.py +++ b/glances/plugins/cloud/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ try: except ImportError as e: import_error_tag = True # Display debug message if import error - logger.warning("Missing Python Lib ({}), Cloud plugin is disabled".format(e)) + logger.warning(f"Missing Python Lib ({e}), Cloud plugin is disabled") else: import_error_tag = False @@ -44,7 +43,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) # We want to display the stat in the curse interface self.display_curse = True @@ -65,7 +64,7 @@ class PluginModel(GlancesPluginModel): self.OPENSTACK.stop() self.OPENSTACKEC2.stop() # Call the father class - super(PluginModel, self).exit() + super().exit() @GlancesPluginModel._check_decorator @GlancesPluginModel._log_result_decorator @@ -145,7 +144,7 @@ class ThreadOpenStack(threading.Thread): def __init__(self): """Init the class.""" logger.debug("cloud plugin - Create thread for OpenStack metadata") - super(ThreadOpenStack, self).__init__() + super().__init__() # Event needed to stop properly the thread self._stopper = threading.Event() # The class return the stats as a dict @@ -161,12 +160,12 @@ class ThreadOpenStack(threading.Thread): return False for k, v in iteritems(self.OPENSTACK_API_METADATA): - r_url = '{}/{}'.format(self.OPENSTACK_API_URL, v) + r_url = f'{self.OPENSTACK_API_URL}/{v}' try: # Local request, a timeout of 3 seconds is OK r = requests.get(r_url, timeout=3) except Exception as e: - logger.debug('cloud plugin - Cannot connect to the OpenStack metadata API {}: {}'.format(r_url, e)) + logger.debug(f'cloud plugin - Cannot connect to the OpenStack metadata API {r_url}: {e}') break else: if r.ok: diff --git a/glances/plugins/connections/__init__.py b/glances/plugins/connections/__init__.py index f11b9aea..143c7041 100644 --- a/glances/plugins/connections/__init__.py +++ b/glances/plugins/connections/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Connections plugin.""" -from __future__ import unicode_literals - import psutil from glances.globals import nativestr @@ -94,7 +91,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, # items_history_list=items_history_list, @@ -123,7 +120,7 @@ class PluginModel(GlancesPluginModel): try: net_connections = psutil.net_connections(kind="tcp") except Exception as e: - logger.warning('Can not get network connections stats ({})'.format(e)) + logger.warning(f'Can not get network connections stats ({e})') logger.info('Disable connections stats') stats['net_connections_enabled'] = False self.stats = stats @@ -146,10 +143,10 @@ class PluginModel(GlancesPluginModel): # Grab connections track directly from the /proc file for i in self.conntrack: try: - with open(self.conntrack[i], 'r') as f: + with open(self.conntrack[i]) as f: stats[i] = float(f.readline().rstrip("\n")) - except (IOError, FileNotFoundError) as e: - logger.warning('Can not get network connections track ({})'.format(e)) + except (OSError, FileNotFoundError) as e: + logger.warning(f'Can not get network connections track ({e})') logger.info('Disable connections track') stats['nf_conntrack_enabled'] = False self.stats = stats @@ -172,7 +169,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specific information try: diff --git a/glances/plugins/containers/__init__.py b/glances/plugins/containers/__init__.py index 024b97fa..bea37ad4 100644 --- a/glances/plugins/containers/__init__.py +++ b/glances/plugins/containers/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -127,7 +126,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -173,7 +172,7 @@ class PluginModel(GlancesPluginModel): if self.podman_extension: self.podman_extension.stop() # Call the father class - super(PluginModel, self).exit() + super().exit() def get_key(self): """Return the key of the list.""" @@ -188,7 +187,7 @@ class PluginModel(GlancesPluginModel): try: ret = deepcopy(self.stats) except KeyError as e: - logger.debug("docker plugin - Docker export error {}".format(e)) + logger.debug(f"docker plugin - Docker export error {e}") ret = [] # Remove fields uses to compute rate @@ -260,7 +259,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() if not self.stats: return False @@ -319,9 +318,9 @@ class PluginModel(GlancesPluginModel): # Title msg = '{}'.format('CONTAINERS') ret.append(self.curse_add_line(msg, "TITLE")) - msg = ' {}'.format(len(self.stats)) + msg = f' {len(self.stats)}' ret.append(self.curse_add_line(msg)) - msg = ' sorted by {}'.format(sort_for_human[self.sort_key]) + msg = f' sorted by {sort_for_human[self.sort_key]}' ret.append(self.curse_add_line(msg)) ret.append(self.curse_new_line()) # Header @@ -402,13 +401,13 @@ class PluginModel(GlancesPluginModel): unit = 'B' try: value = self.auto_unit(int(container['io_rx'])) + unit - msg = '{:>7}'.format(value) + msg = f'{value:>7}' except (KeyError, TypeError): msg = '{:>7}'.format('_') ret.append(self.curse_add_line(msg)) try: value = self.auto_unit(int(container['io_wx'])) + unit - msg = ' {:<7}'.format(value) + msg = f' {value:<7}' except (KeyError, TypeError): msg = ' {:<7}'.format('_') ret.append(self.curse_add_line(msg)) @@ -423,13 +422,13 @@ class PluginModel(GlancesPluginModel): unit = 'b' try: value = self.auto_unit(int(container['network_rx'] * to_bit)) + unit - msg = '{:>7}'.format(value) + msg = f'{value:>7}' except (KeyError, TypeError): msg = '{:>7}'.format('_') ret.append(self.curse_add_line(msg)) try: value = self.auto_unit(int(container['network_tx'] * to_bit)) + unit - msg = ' {:<7}'.format(value) + msg = f' {value:<7}' except (KeyError, TypeError): msg = ' {:<7}'.format('_') ret.append(self.curse_add_line(msg)) diff --git a/glances/plugins/containers/engines/docker.py b/glances/plugins/containers/engines/docker.py index ab27dadc..a72c6bcb 100644 --- a/glances/plugins/containers/engines/docker.py +++ b/glances/plugins/containers/engines/docker.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -24,7 +23,7 @@ try: except Exception as e: import_docker_error_tag = True # Display debug message if import KeyError - logger.warning("Error loading Docker deps Lib. Docker plugin is disabled ({})".format(e)) + logger.warning(f"Error loading Docker deps Lib. Docker plugin is disabled ({e})") else: import_docker_error_tag = False @@ -47,7 +46,7 @@ class DockerStatsFetcher: self._streamer = StatsStreamer(stats_iterable, initial_stream_value={}) def _log_debug(self, msg, exception=None): - logger.debug("containers (Docker) ID: {} - {} ({}) ".format(self._container.id, msg, exception)) + logger.debug(f"containers (Docker) ID: {self._container.id} - {msg} ({exception}) ") logger.debug(self._streamer.stats) def stop(self): @@ -229,7 +228,7 @@ class DockerContainersExtension: # Do not use the timeout option (see issue #1878) self.client = docker.from_env() except Exception as e: - logger.error("{} plugin - Can't connect to Docker ({})".format(self.ext_name, e)) + logger.error(f"{self.ext_name} plugin - Can't connect to Docker ({e})") self.client = None def update_version(self): @@ -256,7 +255,7 @@ class DockerContainersExtension: # The Containers/all key of the configuration file should be set to True containers = self.client.containers.list(all=all_tag) except Exception as e: - logger.error("{} plugin - Can't get containers list ({})".format(self.ext_name, e)) + logger.error(f"{self.ext_name} plugin - Can't get containers list ({e})") return version_stats, [] # Start new thread for new container @@ -264,14 +263,14 @@ class DockerContainersExtension: if container.id not in self.stats_fetchers: # StatsFetcher did not exist in the internal dict # Create it, add it to the internal dict - logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12])) + logger.debug(f"{self.ext_name} plugin - Create thread for container {container.id[:12]}") self.stats_fetchers[container.id] = DockerStatsFetcher(container) # Stop threads for non-existing containers absent_containers = set(iterkeys(self.stats_fetchers)) - set(c.id for c in containers) for container_id in absent_containers: # Stop the StatsFetcher - logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12])) + logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}") self.stats_fetchers[container_id].stop() # Delete the StatsFetcher from the dict del self.stats_fetchers[container_id] diff --git a/glances/plugins/containers/engines/podman.py b/glances/plugins/containers/engines/podman.py index b98bc540..a73f400b 100644 --- a/glances/plugins/containers/engines/podman.py +++ b/glances/plugins/containers/engines/podman.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -21,7 +20,7 @@ try: except Exception as e: import_podman_error_tag = True # Display debug message if import KeyError - logger.warning("Error loading Podman deps Lib. Podman feature in the Containers plugin is disabled ({})".format(e)) + logger.warning(f"Error loading Podman deps Lib. Podman feature in the Containers plugin is disabled ({e})") else: import_podman_error_tag = False @@ -37,7 +36,7 @@ class PodmanContainerStatsFetcher: self._streamer = StatsStreamer(stats_iterable, initial_stream_value={}) def _log_debug(self, msg, exception=None): - logger.debug("containers (Podman) ID: {} - {} ({})".format(self._container.id, msg, exception)) + logger.debug(f"containers (Podman) ID: {self._container.id} - {msg} ({exception})") logger.debug(self._streamer.stats) def stop(self): @@ -96,7 +95,7 @@ class PodmanPodStatsFetcher: self._streamer = StatsStreamer(stats_iterable, initial_stream_value={}, sleep_duration=2) def _log_debug(self, msg, exception=None): - logger.debug("containers (Podman): Pod Manager - {} ({})".format(msg, exception)) + logger.debug(f"containers (Podman): Pod Manager - {msg} ({exception})") logger.debug(self._streamer.stats) def stop(self): @@ -235,7 +234,7 @@ class PodmanContainersExtension: # PodmanClient works lazily, so make a ping to determine if socket is open self.client.ping() except Exception as e: - logger.debug("{} plugin - Can't connect to Podman ({})".format(self.ext_name, e)) + logger.debug(f"{self.ext_name} plugin - Can't connect to Podman ({e})") self.client = None def update_version(self): @@ -267,7 +266,7 @@ class PodmanContainersExtension: if not self.pods_stats_fetcher: self.pods_stats_fetcher = PodmanPodStatsFetcher(self.client.pods) except Exception as e: - logger.error("{} plugin - Can't get containers list ({})".format(self.ext_name, e)) + logger.error(f"{self.ext_name} plugin - Can't get containers list ({e})") return version_stats, [] # Start new thread for new container @@ -275,14 +274,14 @@ class PodmanContainersExtension: if container.id not in self.container_stats_fetchers: # StatsFetcher did not exist in the internal dict # Create it, add it to the internal dict - logger.debug("{} plugin - Create thread for container {}".format(self.ext_name, container.id[:12])) + logger.debug(f"{self.ext_name} plugin - Create thread for container {container.id[:12]}") self.container_stats_fetchers[container.id] = PodmanContainerStatsFetcher(container) # Stop threads for non-existing containers absent_containers = set(iterkeys(self.container_stats_fetchers)) - set(c.id for c in containers) for container_id in absent_containers: # Stop the StatsFetcher - logger.debug("{} plugin - Stop thread for old container {}".format(self.ext_name, container_id[:12])) + logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}") self.container_stats_fetchers[container_id].stop() # Delete the StatsFetcher from the dict del self.container_stats_fetchers[container_id] diff --git a/glances/plugins/containers/stats_streamer.py b/glances/plugins/containers/stats_streamer.py index 7dc967fe..999c8dcb 100644 --- a/glances/plugins/containers/stats_streamer.py +++ b/glances/plugins/containers/stats_streamer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -63,7 +62,7 @@ class StatsStreamer: break except Exception as e: - logger.debug("docker plugin - Exception thrown during run ({})".format(e)) + logger.debug(f"docker plugin - Exception thrown during run ({e})") self.stop() def _pre_update_hook(self): diff --git a/glances/plugins/core/__init__.py b/glances/plugins/core/__init__.py index ffede532..d4e6b31e 100644 --- a/glances/plugins/core/__init__.py +++ b/glances/plugins/core/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -34,7 +33,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description) + super().__init__(args=args, config=config, fields_description=fields_description) # We dot not want to display the stat in the curse interface # The core number is displayed by the load plugin diff --git a/glances/plugins/cpu/__init__.py b/glances/plugins/cpu/__init__.py index 9379fd09..63d051d6 100644 --- a/glances/plugins/cpu/__init__.py +++ b/glances/plugins/cpu/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -144,7 +143,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the CPU plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -273,7 +272,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert and log diff --git a/glances/plugins/diskio/__init__.py b/glances/plugins/diskio/__init__.py index 67ea1205..4c98c6af 100644 --- a/glances/plugins/diskio/__init__.py +++ b/glances/plugins/diskio/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Disk I/O plugin.""" -from __future__ import unicode_literals - import psutil from glances.globals import nativestr @@ -62,7 +59,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, @@ -142,7 +139,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Check if the stats should be hidden self.update_views_hidden() @@ -172,7 +169,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 13 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header @@ -206,13 +203,13 @@ class PluginModel(GlancesPluginModel): # count txps = self.auto_unit(i.get('read_count_rate_per_sec', None)) rxps = self.auto_unit(i.get('write_count_rate_per_sec', None)) - msg = '{:>7}'.format(txps) + msg = f'{txps:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='read_count', option='decoration') ) ) - msg = '{:>7}'.format(rxps) + msg = f'{rxps:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='write_count', option='decoration') @@ -222,13 +219,13 @@ class PluginModel(GlancesPluginModel): # Bitrate txps = self.auto_unit(i.get('read_bytes_rate_per_sec', None)) rxps = self.auto_unit(i.get('write_bytes_rate_per_sec', None)) - msg = '{:>7}'.format(txps) + msg = f'{txps:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='read_bytes', option='decoration') ) ) - msg = '{:>7}'.format(rxps) + msg = f'{rxps:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='write_bytes', option='decoration') diff --git a/glances/plugins/folders/__init__.py b/glances/plugins/folders/__init__.py index 9ebb8ea9..dd5ce09a 100644 --- a/glances/plugins/folders/__init__.py +++ b/glances/plugins/folders/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Folder plugin.""" -from __future__ import unicode_literals - from glances.folder_list import FolderList as glancesFolderList from glances.globals import nativestr from glances.logger import logger @@ -56,9 +53,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) self.args = args self.config = config @@ -138,7 +133,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 7 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header diff --git a/glances/plugins/fs/__init__.py b/glances/plugins/fs/__init__.py index 49bb4f29..74df193c 100644 --- a/glances/plugins/fs/__init__.py +++ b/glances/plugins/fs/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """File system plugin.""" -from __future__ import unicode_literals - import operator import psutil @@ -98,7 +95,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, @@ -241,7 +238,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert @@ -264,7 +261,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 13 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Build the string message diff --git a/glances/plugins/gpu/__init__.py b/glances/plugins/gpu/__init__.py index 47ccf77e..8e8f601c 100644 --- a/glances/plugins/gpu/__init__.py +++ b/glances/plugins/gpu/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -67,7 +66,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, @@ -89,7 +88,7 @@ class PluginModel(GlancesPluginModel): self.amd.exit() # Call the father exit method - super(PluginModel, self).exit() + super().exit() def get_key(self): """Return the key of the list.""" @@ -150,7 +149,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert @@ -190,7 +189,7 @@ class PluginModel(GlancesPluginModel): # Header header = '' if len(self.stats) > 1: - header += '{}'.format(len(self.stats)) + header += f'{len(self.stats)}' if same_name: header += ' {}'.format(gpu_stats['name']) else: @@ -213,7 +212,7 @@ class PluginModel(GlancesPluginModel): except TypeError: mean_proc_msg = '{:>4}'.format('N/A') else: - mean_proc_msg = '{:>3.0f}%'.format(mean_proc) + mean_proc_msg = f'{mean_proc:>3.0f}%' if len(self.stats) > 1: msg = '{:13}'.format('proc mean:') else: @@ -232,7 +231,7 @@ class PluginModel(GlancesPluginModel): except TypeError: mean_mem_msg = '{:>4}'.format('N/A') else: - mean_mem_msg = '{:>3.0f}%'.format(mean_mem) + mean_mem_msg = f'{mean_mem:>3.0f}%' if len(self.stats) > 1: msg = '{:13}'.format('mem mean:') else: @@ -255,7 +254,7 @@ class PluginModel(GlancesPluginModel): if args.fahrenheit: mean_temperature = to_fahrenheit(mean_temperature) unit = 'F' - mean_temperature_msg = '{:>3.0f}{}'.format(mean_temperature, unit) + mean_temperature_msg = f'{mean_temperature:>3.0f}{unit}' if len(self.stats) > 1: msg = '{:13}'.format('temp mean:') else: @@ -283,7 +282,7 @@ class PluginModel(GlancesPluginModel): mem_msg = '{:>3.0f}%'.format(gpu_stats['mem']) except (ValueError, TypeError): mem_msg = '{:>4}'.format('N/A') - msg = '{} {} mem {}'.format(id_msg, proc_msg, mem_msg) + msg = f'{id_msg} {proc_msg} mem {mem_msg}' ret.append(self.curse_add_line(msg)) return ret diff --git a/glances/plugins/gpu/cards/amd.py b/glances/plugins/gpu/cards/amd.py index 2223fae4..eb4ead3a 100644 --- a/glances/plugins/gpu/cards/amd.py +++ b/glances/plugins/gpu/cards/amd.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # diff --git a/glances/plugins/gpu/cards/nvidia.py b/glances/plugins/gpu/cards/nvidia.py index a6473b24..2c9fe54a 100644 --- a/glances/plugins/gpu/cards/nvidia.py +++ b/glances/plugins/gpu/cards/nvidia.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -17,7 +16,7 @@ try: except Exception as e: nvidia_gpu_enable = False # Display debug message if import KeyError - logger.warning("Missing Python Lib ({}), Nvidia GPU plugin is disabled".format(e)) + logger.warning(f"Missing Python Lib ({e}), Nvidia GPU plugin is disabled") else: nvidia_gpu_enable = True @@ -43,7 +42,7 @@ class NvidiaGPU: try: pynvml.nvmlShutdown() except Exception as e: - logger.debug("pynvml failed to shutdown correctly ({})".format(e)) + logger.debug(f"pynvml failed to shutdown correctly ({e})") def get_device_stats(self): """Get Nvidia GPU stats.""" diff --git a/glances/plugins/help/__init__.py b/glances/plugins/help/__init__.py index 6f8c46ac..19d84d90 100644 --- a/glances/plugins/help/__init__.py +++ b/glances/plugins/help/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -13,7 +12,6 @@ Help plugin. Just a stupid plugin to display the help screen. """ -import sys from itertools import chain from glances import __version__, psutil_version @@ -26,7 +24,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) # Set the config instance self.config = config @@ -36,12 +34,7 @@ class PluginModel(GlancesPluginModel): self.display_curse = True # init data dictionary, to preserve insertion order - if sys.version_info < (3, 6): - from collections import OrderedDict - - self.view_data = OrderedDict() - else: - self.view_data = {} + self.view_data = {} self.generate_view_data() def reset(self): @@ -53,10 +46,10 @@ class PluginModel(GlancesPluginModel): def generate_view_data(self): """Generate the views.""" self.view_data['version'] = '{} {}'.format('Glances', __version__) - self.view_data['psutil_version'] = ' with psutil {}'.format(psutil_version) + self.view_data['psutil_version'] = f' with psutil {psutil_version}' try: - self.view_data['configuration_file'] = 'Configuration file: {}'.format(self.config.loaded_config_file) + self.view_data['configuration_file'] = f'Configuration file: {self.config.loaded_config_file}' except AttributeError: pass diff --git a/glances/plugins/ip/__init__.py b/glances/plugins/ip/__init__.py index 09c3c6c5..6d5f55f2 100644 --- a/glances/plugins/ip/__init__.py +++ b/glances/plugins/ip/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ try: import netifaces except ImportError as e: import_error_tag = True - logger.warning("Missing Python Lib ({}), IP plugin is disabled".format(e)) + logger.warning(f"Missing Python Lib ({e}), IP plugin is disabled") else: import_error_tag = False @@ -66,7 +65,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description) + super().__init__(args=args, config=config, fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True @@ -104,7 +103,7 @@ class PluginModel(GlancesPluginModel): try: default_gw = netifaces.gateways()['default'][netifaces.AF_INET] except (KeyError, AttributeError) as e: - logger.debug("Cannot grab default gateway IP address ({})".format(e)) + logger.debug(f"Cannot grab default gateway IP address ({e})") return self.get_init_value() else: stats['gateway'] = default_gw[0] @@ -113,7 +112,7 @@ class PluginModel(GlancesPluginModel): address = netifaces.ifaddresses(default_gw[1])[netifaces.AF_INET][0]['addr'] mask = netifaces.ifaddresses(default_gw[1])[netifaces.AF_INET][0]['netmask'] except (KeyError, AttributeError) as e: - logger.debug("Cannot grab private IP address ({})".format(e)) + logger.debug(f"Cannot grab private IP address ({e})") return self.get_init_value() else: stats['address'] = address @@ -129,7 +128,7 @@ class PluginModel(GlancesPluginModel): self.public_info = PublicIpInfo(self.public_api, self.public_username, self.public_password).get() self.public_address = self.public_info['ip'] except (KeyError, AttributeError, TypeError) as e: - logger.debug("Cannot grab public IP information ({})".format(e)) + logger.debug(f"Cannot grab public IP information ({e})") else: stats['public_address'] = ( self.public_address if not self.args.hide_public_info else self.__hide_ip(self.public_address) @@ -211,7 +210,7 @@ class PluginModel(GlancesPluginModel): return sum(bin(int(x)).count('1') for x in ip.split('.')) -class PublicIpInfo(object): +class PublicIpInfo: """Get public IP information from online service.""" def __init__(self, url, username, password, timeout=2): @@ -242,11 +241,11 @@ class PublicIpInfo(object): try: response = urlopen_auth(url, username, password).read() except Exception as e: - logger.debug("IP plugin - Cannot get public IP information from {} ({})".format(url, e)) + logger.debug(f"IP plugin - Cannot get public IP information from {url} ({e})") queue_target.put(None) else: try: queue_target.put(loads(response)) except (ValueError, KeyError) as e: - logger.debug("IP plugin - Cannot load public IP information from {} ({})".format(url, e)) + logger.debug(f"IP plugin - Cannot load public IP information from {url} ({e})") queue_target.put(None) diff --git a/glances/plugins/irq/__init__.py b/glances/plugins/irq/__init__.py index c4c5004c..ff43ae88 100644 --- a/glances/plugins/irq/__init__.py +++ b/glances/plugins/irq/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -42,9 +41,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True @@ -86,7 +83,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() def msg_curse(self, args=None, max_width=None): """Return the dict to display in the curse interface.""" @@ -103,7 +100,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 7 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Build the string message @@ -123,7 +120,7 @@ class PluginModel(GlancesPluginModel): return ret -class GlancesIRQ(object): +class GlancesIRQ: """This class manages the IRQ file.""" IRQ_FILE = '/proc/interrupts' @@ -169,7 +166,7 @@ class GlancesIRQ(object): irq_line = splitted_line[0].replace(':', '') if irq_line.isdigit(): # If the first column is a digit, use the alias (last column) - irq_line += '_{}'.format(splitted_line[-1]) + irq_line += f'_{splitted_line[-1]}' return irq_line def __sum(self, line): @@ -216,7 +213,7 @@ class GlancesIRQ(object): } self.stats.append(irq_current) self.lasts[irq_line] = current_irqs - except (OSError, IOError): + except OSError: pass return self.stats diff --git a/glances/plugins/load/__init__.py b/glances/plugins/load/__init__.py index 9c3c81bc..d3c0c26d 100644 --- a/glances/plugins/load/__init__.py +++ b/glances/plugins/load/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -66,7 +65,7 @@ nb_phys_core = 1 try: core = CorePluginModel().update() except Exception as e: - logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e)) + logger.warning(f'Error: Can not retrieve the CPU core number (set it to 1) ({e})') else: if 'log' in core: nb_log_core = core['log'] @@ -82,7 +81,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -128,7 +127,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information try: @@ -164,17 +163,17 @@ class PluginModel(GlancesPluginModel): # Loop over 1min, 5min and 15min load for load_time in ['1', '5', '15']: ret.append(self.curse_new_line()) - msg = '{:7}'.format('{} min'.format(load_time)) + msg = '{:7}'.format(f'{load_time} min') ret.append(self.curse_add_line(msg)) if args.disable_irix and get_nb_log_core() != 0: # Enable Irix mode for load (see issue #1554) - load_stat = self.stats['min{}'.format(load_time)] / get_nb_log_core() * 100 - msg = '{:>5.1f}%'.format(load_stat) + load_stat = self.stats[f'min{load_time}'] / get_nb_log_core() * 100 + msg = f'{load_stat:>5.1f}%' else: # Default mode for load - load_stat = self.stats['min{}'.format(load_time)] - msg = '{:>6.2f}'.format(load_stat) - ret.append(self.curse_add_line(msg, self.get_views(key='min{}'.format(load_time), option='decoration'))) + load_stat = self.stats[f'min{load_time}'] + msg = f'{load_stat:>6.2f}' + ret.append(self.curse_add_line(msg, self.get_views(key=f'min{load_time}', option='decoration'))) return ret diff --git a/glances/plugins/mem/__init__.py b/glances/plugins/mem/__init__.py index b462d9ee..a72f9401 100644 --- a/glances/plugins/mem/__init__.py +++ b/glances/plugins/mem/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -113,7 +112,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -219,7 +218,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert and log diff --git a/glances/plugins/memswap/__init__.py b/glances/plugins/memswap/__init__.py index 534848ce..c3b1f3a9 100644 --- a/glances/plugins/memswap/__init__.py +++ b/glances/plugins/memswap/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -60,7 +59,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -145,7 +144,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert and log diff --git a/glances/plugins/network/__init__.py b/glances/plugins/network/__init__.py index 3b5f05f2..da582db6 100644 --- a/glances/plugins/network/__init__.py +++ b/glances/plugins/network/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,8 +8,6 @@ """Network plugin.""" -from __future__ import unicode_literals - import psutil from glances.logger import logger @@ -73,7 +70,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, @@ -131,7 +128,7 @@ class PluginModel(GlancesPluginModel): try: net_io_counters = psutil.net_io_counters(pernic=True) except UnicodeDecodeError as e: - logger.debug('Can not get network interface counters ({})'.format(e)) + logger.debug(f'Can not get network interface counters ({e})') return self.stats # Grab interface's status (issue #765) @@ -145,7 +142,7 @@ class PluginModel(GlancesPluginModel): net_status = psutil.net_if_stats() except OSError as e: # see psutil #797/glances #1106 - logger.debug('Can not get network interface status ({})'.format(e)) + logger.debug(f'Can not get network interface status ({e})') for interface_name, interface_stat in net_io_counters.items(): # Do not take hidden interface into account @@ -181,7 +178,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Check if the stats should be hidden self.update_views_hidden() @@ -227,7 +224,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 12 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header @@ -301,16 +298,16 @@ class PluginModel(GlancesPluginModel): msg = '{:{width}}'.format(if_name, width=name_max_width) ret.append(self.curse_add_line(msg)) if args.network_sum: - msg = '{:>14}'.format(ax) + msg = f'{ax:>14}' ret.append(self.curse_add_line(msg)) else: - msg = '{:>7}'.format(rx) + msg = f'{rx:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='bytes_recv', option='decoration') ) ) - msg = '{:>7}'.format(tx) + msg = f'{tx:>7}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='bytes_sent', option='decoration') diff --git a/glances/plugins/now/__init__.py b/glances/plugins/now/__init__.py index 8482d70b..abea0265 100644 --- a/glances/plugins/now/__init__.py +++ b/glances/plugins/now/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -38,9 +37,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, fields_description=fields_description, stats_init_value={} - ) + super().__init__(args=args, config=config, fields_description=fields_description, stats_init_value={}) # We want to display the stat in the curse interface self.display_curse = True diff --git a/glances/plugins/percpu/__init__.py b/glances/plugins/percpu/__init__.py index 9cbcc9c0..66e2c438 100644 --- a/glances/plugins/percpu/__init__.py +++ b/glances/plugins/percpu/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -96,7 +95,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, @@ -159,7 +158,7 @@ class PluginModel(GlancesPluginModel): for stat in header: if stat not in self.stats[0]: continue - msg = '{:>7}'.format(stat) + msg = f'{stat:>7}' ret.append(self.curse_add_line(msg)) # Manage the maximum number of CPU to display (related to enhancement request #2734) @@ -176,9 +175,9 @@ class PluginModel(GlancesPluginModel): try: cpu_id = cpu[cpu['key']] if cpu_id < 10: - msg = 'CPU{:1} '.format(cpu_id) + msg = f'CPU{cpu_id:1} ' else: - msg = '{:4} '.format(cpu_id) + msg = f'{cpu_id:4} ' except TypeError: # TypeError: string indices must be integers (issue #1027) msg = '{:4} '.format('?') @@ -187,7 +186,7 @@ class PluginModel(GlancesPluginModel): if stat not in self.stats[0]: continue try: - msg = '{:6.1f}%'.format(cpu[stat]) + msg = f'{cpu[stat]:6.1f}%' except TypeError: msg = '{:>6}%'.format('?') ret.append(self.curse_add_line(msg, self.get_alert(cpu[stat], header=stat))) @@ -204,7 +203,7 @@ class PluginModel(GlancesPluginModel): [i[stat] for i in percpu_list[0 : self.max_cpu_display]] ) try: - msg = '{:6.1f}%'.format(cpu_stat) + msg = f'{cpu_stat:6.1f}%' except TypeError: msg = '{:>6}%'.format('?') ret.append(self.curse_add_line(msg, self.get_alert(cpu_stat, header=stat))) diff --git a/glances/plugins/plugin/model.py b/glances/plugins/plugin/model.py index 9e40fce1..502122ca 100644 --- a/glances/plugins/plugin/model.py +++ b/glances/plugins/plugin/model.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -43,7 +42,7 @@ fields_unit_type = { } -class GlancesPluginModel(object): +class GlancesPluginModel: """Main class for Glances plugin model.""" def __init__(self, args=None, config=None, items_history_list=None, stats_init_value={}, fields_description=None): @@ -77,7 +76,7 @@ class GlancesPluginModel(object): if self.plugin_name.startswith('glances_'): self.plugin_name = self.plugin_name.split('glances_')[1] - logger.debug("Init {} plugin".format(self.plugin_name)) + logger.debug(f"Init {self.plugin_name} plugin") # Init the args self.args = args @@ -96,7 +95,7 @@ class GlancesPluginModel(object): # Init the limits (configuration keys) dictionary self._limits = dict() if config is not None: - logger.debug('Load section {} in {}'.format(self.plugin_name, config.config_file_paths())) + logger.debug(f'Load section {self.plugin_name} in {config.config_file_paths()}') self.load_limits(config=config) # Init the alias (dictionnary) @@ -147,7 +146,7 @@ class GlancesPluginModel(object): def exit(self): """Just log an event when Glances exit.""" - logger.debug("Stop the {} plugin".format(self.plugin_name)) + logger.debug(f"Stop the {self.plugin_name} plugin") def get_key(self): """Return the key of the list.""" @@ -174,14 +173,14 @@ class GlancesPluginModel(object): """Init the stats history (dict of GlancesAttribute).""" if self.history_enable(): init_list = [a['name'] for a in self.get_items_history_list()] - logger.debug("Stats history activated for plugin {} (items: {})".format(self.plugin_name, init_list)) + logger.debug(f"Stats history activated for plugin {self.plugin_name} (items: {init_list})") return GlancesHistory() def reset_stats_history(self): """Reset the stats history (dict of GlancesAttribute).""" if self.history_enable(): reset_list = [a['name'] for a in self.get_items_history_list()] - logger.debug("Reset history for plugin {} (items: {})".format(self.plugin_name, reset_list)) + logger.debug(f"Reset history for plugin {self.plugin_name} (items: {reset_list})") self.stats_history.reset() def update_stats_history(self): @@ -414,7 +413,7 @@ class GlancesPluginModel(object): try: return {value: [i for i in self.get_raw() if i[item] == value]} except (KeyError, ValueError) as e: - logger.error("Cannot get item({})=value({}) ({})".format(item, value, e)) + logger.error(f"Cannot get item({item})=value({value}) ({e})") return None def get_stats_value(self, item, value): @@ -582,7 +581,7 @@ class GlancesPluginModel(object): self._limits[limit] = config.get_float_value(self.plugin_name, level) except ValueError: self._limits[limit] = config.get_value(self.plugin_name, level).split(",") - logger.debug("Load limit: {} = {}".format(limit, self._limits[limit])) + logger.debug(f"Load limit: {limit} = {self._limits[limit]}") return True @@ -613,13 +612,13 @@ class GlancesPluginModel(object): def set_limits(self, item, value): """Set the limits object.""" - self._limits['{}_{}'.format(self.plugin_name, item)] = value + self._limits[f'{self.plugin_name}_{item}'] = value def get_limits(self, item=None): """Return the limits object.""" if item is None: return self._limits - return self._limits.get('{}_{}'.format(self.plugin_name, item), None) + return self._limits.get(f'{self.plugin_name}_{item}', None) def get_stats_action(self): """Return stats for the action. @@ -1025,7 +1024,7 @@ class GlancesPluginModel(object): value = self.stats.get(key, None) if width is None: - msg_item = header + '{}'.format(key_name) + separator + msg_item = header + f'{key_name}' + separator msg_template_float = '{:.1f}{}' msg_template = '{}{}' else: @@ -1124,7 +1123,7 @@ class GlancesPluginModel(object): elif symbol in 'K': decimal_precision = 0 return '{:.{decimal}f}{symbol}'.format(value, decimal=decimal_precision, symbol=symbol) - return '{!s}'.format(number) + return f'{number!s}' def trend_msg(self, trend, significant=1): """Return the trend message. @@ -1170,11 +1169,9 @@ class GlancesPluginModel(object): counter = Counter() ret = fct(*args, **kw) duration = counter.get() - logger.debug( - "{} {} {} return {} in {} seconds".format( - args[0].__class__.__name__, args[0].__class__.__module__, fct.__name__, ret, duration - ) - ) + class_name = args[0].__class__.__name__ + class_module = args[0].__class__.__module__ + logger.debug(f"{class_name} {class_module} {fct.__name__} return {ret} in {duration} seconds") return ret return wrapper diff --git a/glances/plugins/ports/__init__.py b/glances/plugins/ports/__init__.py index 78e58347..5ffce494 100644 --- a/glances/plugins/ports/__init__.py +++ b/glances/plugins/ports/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -29,7 +28,7 @@ try: requests_tag = True except ImportError as e: requests_tag = False - logger.warning("Missing Python Lib ({}), Ports plugin is limited to port scanning".format(e)) + logger.warning(f"Missing Python Lib ({e}), Ports plugin is limited to port scanning") # Fields description # description: human readable description @@ -72,9 +71,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) self.args = args self.config = config @@ -95,7 +92,7 @@ class PluginModel(GlancesPluginModel): if self._thread is not None: self._thread.stop() # Call the father class - super(PluginModel, self).exit() + super().exit() def get_key(self): """Return the key of the list.""" @@ -183,7 +180,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 7 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Build the string message @@ -199,11 +196,11 @@ class PluginModel(GlancesPluginModel): status = 'Timeout' else: # Convert second to ms - status = '{0:.0f}ms'.format(p['status'] * 1000.0) + status = '{:.0f}ms'.format(p['status'] * 1000.0) msg = '{:{width}}'.format(p['description'][0:name_max_width], width=name_max_width) ret.append(self.curse_add_line(msg)) - msg = '{:>9}'.format(status) + msg = f'{status:>9}' ret.append(self.curse_add_line(msg, self.get_ports_alert(p, header=p['indice'] + '_rtt'))) ret.append(self.curse_new_line()) elif 'url' in p: @@ -215,7 +212,7 @@ class PluginModel(GlancesPluginModel): status = 'Scanning' else: status = p['status'] - msg = '{:>9}'.format(status) + msg = f'{status:>9}' ret.append(self.curse_add_line(msg, self.get_web_alert(p, header=p['indice'] + '_rtt'))) ret.append(self.curse_new_line()) @@ -237,8 +234,8 @@ class ThreadScanner(threading.Thread): def __init__(self, stats): """Init the class.""" - logger.debug("ports plugin - Create thread for scan list {}".format(stats)) - super(ThreadScanner, self).__init__() + logger.debug(f"ports plugin - Create thread for scan list {stats}") + super().__init__() # Event needed to stop properly the thread self._stopper = threading.Event() # The class return the stats as a list of dict @@ -283,7 +280,7 @@ class ThreadScanner(threading.Thread): def stop(self, timeout=None): """Stop the thread.""" - logger.debug("ports plugin - Close thread for scan list {}".format(self._stats)) + logger.debug(f"ports plugin - Close thread for scan list {self._stats}") self._stopper.set() def stopped(self): @@ -321,7 +318,7 @@ class ThreadScanner(threading.Thread): try: ip = socket.gethostbyname(hostname) except Exception as e: - logger.debug("{}: Cannot convert {} to IP address ({})".format(self.plugin_name, hostname, e)) + logger.debug(f"{self.plugin_name}: Cannot convert {hostname} to IP address ({e})") return ip def _port_scan_icmp(self, port): @@ -379,7 +376,7 @@ class ThreadScanner(threading.Thread): socket.setdefaulttimeout(port['timeout']) _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except Exception as e: - logger.debug("{}: Error while creating scanning socket ({})".format(self.plugin_name, e)) + logger.debug(f"{self.plugin_name}: Error while creating scanning socket ({e})") # Scan port ip = self._resolv_name(port['host']) @@ -387,7 +384,7 @@ class ThreadScanner(threading.Thread): try: ret = _socket.connect_ex((ip, int(port['port']))) except Exception as e: - logger.debug("{}: Error while scanning port {} ({})".format(self.plugin_name, port, e)) + logger.debug(f"{self.plugin_name}: Error while scanning port {port} ({e})") else: if ret == 0: port['status'] = counter.get() diff --git a/glances/plugins/processcount/__init__.py b/glances/plugins/processcount/__init__.py index 53479ead..3afb73c7 100644 --- a/glances/plugins/processcount/__init__.py +++ b/glances/plugins/processcount/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -113,9 +112,9 @@ class PluginModel(GlancesPluginModel): if glances_processes.process_filter is not None: msg = 'Processes filter:' ret.append(self.curse_add_line(msg, "TITLE")) - msg = ' {} '.format(glances_processes.process_filter) + msg = f' {glances_processes.process_filter} ' if glances_processes.process_filter_key is not None: - msg += 'on column {} '.format(glances_processes.process_filter_key) + msg += f'on column {glances_processes.process_filter_key} ' ret.append(self.curse_add_line(msg, "FILTER")) msg = '(\'ENTER\' to edit, \'E\' to reset)' ret.append(self.curse_add_line(msg)) @@ -144,7 +143,7 @@ class PluginModel(GlancesPluginModel): msg = ' {} slp,'.format(self.stats['sleeping']) ret.append(self.curse_add_line(msg)) - msg = ' {} oth '.format(other) + msg = f' {other} oth ' ret.append(self.curse_add_line(msg)) # Display sort information @@ -156,9 +155,9 @@ class PluginModel(GlancesPluginModel): if glances_processes.auto_sort: msg += ' sorted automatically' ret.append(self.curse_add_line(msg)) - msg = ' by {}'.format(sort_human) + msg = f' by {sort_human}' else: - msg += ' sorted by {}'.format(sort_human) + msg += f' sorted by {sort_human}' ret.append(self.curse_add_line(msg)) # Return the message with decoration diff --git a/glances/plugins/processlist/__init__.py b/glances/plugins/processlist/__init__.py index fab3e12b..e5be4d82 100644 --- a/glances/plugins/processlist/__init__.py +++ b/glances/plugins/processlist/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -155,9 +154,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, fields_description=fields_description, stats_init_value=[] - ) + super().__init__(args=args, config=config, fields_description=fields_description, stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True @@ -341,11 +338,11 @@ class PluginModel(GlancesPluginModel): else: hours, minutes, seconds = seconds_to_hms(user_system_time) if hours > 99: - msg = '{:<7}h'.format(hours) + msg = f'{hours:<7}h' elif 0 < hours < 100: - msg = '{}h{}:{}'.format(hours, minutes, seconds) + msg = f'{hours}h{minutes}:{seconds}' else: - msg = '{}:{}'.format(minutes, seconds) + msg = f'{minutes}:{seconds}' msg = self.layout_stat['time'].format(msg) if hours > 0: ret = self.curse_add_line(msg, decoration='CPU_TIME', optional=True) @@ -502,7 +499,7 @@ class PluginModel(GlancesPluginModel): ret.append(self.curse_add_line(msg, decoration=process_decoration, splittable=True)) except (TypeError, UnicodeEncodeError) as e: # Avoid crash after running fine for several hours #1335 - logger.debug("Can not decode command line '{}' ({})".format(cmdline, e)) + logger.debug(f"Can not decode command line '{cmdline}' ({e})") ret.append(self.curse_add_line('', splittable=True)) return ret @@ -643,7 +640,7 @@ class PluginModel(GlancesPluginModel): # value is a number which goes from 0 to 7. # The higher the value, the lower the I/O priority of the process. if hasattr(p['ionice'], 'value') and p['ionice'].value != 0: - msg += ' (value %s/7)' % str(p['ionice'].value) + msg += ' (value {}/7)'.format(str(p['ionice'].value)) ret.append(self.curse_add_line(msg, splittable=True)) # Second line is memory info @@ -826,7 +823,7 @@ class PluginModel(GlancesPluginModel): msg = ' < {}'.format('current') ret.append(self.curse_add_line(msg, optional=True)) else: - msg = ' < {}'.format(mmm) + msg = f' < {mmm}' ret.append(self.curse_add_line(msg, optional=True)) msg = ' (\'M\' to reset)' ret.append(self.curse_add_line(msg, optional=True)) diff --git a/glances/plugins/psutilversion/__init__.py b/glances/plugins/psutilversion/__init__.py index 5544a11f..ab23454f 100644 --- a/glances/plugins/psutilversion/__init__.py +++ b/glances/plugins/psutilversion/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) self.reset() diff --git a/glances/plugins/quicklook/__init__.py b/glances/plugins/quicklook/__init__.py index 8646298d..0c45d9a3 100644 --- a/glances/plugins/quicklook/__init__.py +++ b/glances/plugins/quicklook/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -84,7 +83,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the quicklook plugin.""" - super(PluginModel, self).__init__( + super().__init__( args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) @@ -97,7 +96,7 @@ class PluginModel(GlancesPluginModel): # Define the stats list self.stats_list = self.get_conf_value('list', default=self.DEFAULT_STATS_LIST) if not set(self.stats_list).issubset(self.AVAILABLE_STATS_LIST): - logger.warning('Quicklook plugin: Invalid stats list: {}'.format(self.stats_list)) + logger.warning(f'Quicklook plugin: Invalid stats list: {self.stats_list}') self.stats_list = self.AVAILABLE_STATS_LIST @GlancesPluginModel._check_decorator @@ -152,7 +151,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Alert for CPU, MEM and SWAP for key in self.stats_list: @@ -176,7 +175,7 @@ class PluginModel(GlancesPluginModel): if not max_width: # No max_width defined, return an empty message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Define the data: Bar (default behavior) or Sparkline @@ -221,7 +220,7 @@ class PluginModel(GlancesPluginModel): else: # Bar only the last value data[key].percent = self.stats[key] - msg = '{:4} '.format(key.upper()) + msg = f'{key.upper():4} ' ret.extend(self._msg_create_line(msg, data[key], key)) ret.append(self.curse_new_line()) @@ -258,9 +257,9 @@ class PluginModel(GlancesPluginModel): # Bar will only display the last value data[key].percent = cpu['total'] if cpu_id < 10: - msg = '{:3}{} '.format(key.upper(), cpu_id) + msg = f'{key.upper():3}{cpu_id} ' else: - msg = '{:4} '.format(cpu_id) + msg = f'{cpu_id:4} ' ret.extend(self._msg_create_line(msg, data[key], key)) ret.append(self.curse_new_line()) @@ -282,7 +281,7 @@ class PluginModel(GlancesPluginModel): sum_other.percent = sum([i['total'] for i in percpu_list[self.max_cpu_display :]]) / len( percpu_list[self.max_cpu_display :] ) - msg = msg = '{:3}* '.format(key.upper()) + msg = msg = f'{key.upper():3}* ' ret.extend(self._msg_create_line(msg, sum_other, key)) ret.append(self.curse_new_line()) diff --git a/glances/plugins/raid/__init__.py b/glances/plugins/raid/__init__.py index c9fcdf7f..3fda53d0 100644 --- a/glances/plugins/raid/__init__.py +++ b/glances/plugins/raid/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -18,7 +17,7 @@ try: from pymdstat import MdStat except ImportError as e: import_error_tag = True - logger.warning("Missing Python Lib ({}), Raid plugin is disabled".format(e)) + logger.warning(f"Missing Python Lib ({e}), Raid plugin is disabled") else: import_error_tag = False @@ -31,7 +30,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) # We want to display the stat in the curse interface self.display_curse = True @@ -54,7 +53,7 @@ class PluginModel(GlancesPluginModel): # mds = MdStat(path='/home/nicolargo/dev/pymdstat/tests/mdstat.10') stats = mds.get_stats()['arrays'] except Exception as e: - logger.debug("Can not grab RAID stats (%s)" % e) + logger.debug(f"Can not grab RAID stats ({e})") return self.stats elif self.input_method == 'snmp': @@ -81,7 +80,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 12 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header @@ -108,7 +107,7 @@ class PluginModel(GlancesPluginModel): # Data: RAID type name | disk used | disk available array_type = self.stats[array]['type'].upper() if self.stats[array]['type'] is not None else 'UNKNOWN' # Build the full name = array type + array name - full_name = '{} {}'.format(array_type, array) + full_name = f'{array_type} {array}' msg = '{:{width}}'.format(full_name, width=name_max_width) ret.append(self.curse_add_line(msg)) if self.stats[array]['type'] == 'raid0' and self.stats[array]['status'] == 'active': @@ -134,7 +133,7 @@ class PluginModel(GlancesPluginModel): ret.append(self.curse_new_line()) msg = ' {} disk {}: '.format(tree_char, self.stats[array]['components'][component]) ret.append(self.curse_add_line(msg)) - msg = '{}'.format(component) + msg = f'{component}' ret.append(self.curse_add_line(msg)) if self.stats[array]['type'] != 'raid0' and (self.stats[array]['used'] < self.stats[array]['available']): # Display current array configuration diff --git a/glances/plugins/sensors/__init__.py b/glances/plugins/sensors/__init__.py index 4eb1f116..9419a559 100644 --- a/glances/plugins/sensors/__init__.py +++ b/glances/plugins/sensors/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -83,29 +82,27 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__( - args=args, config=config, stats_init_value=[], fields_description=fields_description - ) + super().__init__(args=args, config=config, stats_init_value=[], fields_description=fields_description) start_duration = Counter() # Init the sensor class start_duration.reset() glances_grab_sensors_cpu_temp = GlancesGrabSensors(SensorType.CPU_TEMP) - logger.debug("CPU Temp sensor plugin init duration: {} seconds".format(start_duration.get())) + logger.debug(f"CPU Temp sensor plugin init duration: {start_duration.get()} seconds") start_duration.reset() glances_grab_sensors_fan_speed = GlancesGrabSensors(SensorType.FAN_SPEED) - logger.debug("Fan speed sensor plugin init duration: {} seconds".format(start_duration.get())) + logger.debug(f"Fan speed sensor plugin init duration: {start_duration.get()} seconds") # Instance for the HDDTemp Plugin in order to display the hard disks temperatures start_duration.reset() hddtemp_plugin = HddTempPluginModel(args=args, config=config) - logger.debug("HDDTemp sensor plugin init duration: {} seconds".format(start_duration.get())) + logger.debug(f"HDDTemp sensor plugin init duration: {start_duration.get()} seconds") # Instance for the BatPercent in order to display the batteries capacities start_duration.reset() batpercent_plugin = BatPercentPluginModel(args=args, config=config) - logger.debug("Battery sensor plugin init duration: {} seconds".format(start_duration.get())) + logger.debug(f"Battery sensor plugin init duration: {start_duration.get()} seconds") self.sensors_grab_map: Dict[SensorType, Any] = {} @@ -214,7 +211,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert @@ -272,7 +269,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 12 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header @@ -303,8 +300,8 @@ class PluginModel(GlancesPluginModel): value = i['value'] unit = i['unit'] try: - msg = '{:.0f}{}{}'.format(value, unit, trend) - msg = '{:>14}'.format(msg) + msg = f'{value:.0f}{unit}{trend}' + msg = f'{msg:>14}' ret.append( self.curse_add_line( msg, self.get_views(item=i[self.get_key()], key='value', option='decoration') @@ -316,7 +313,7 @@ class PluginModel(GlancesPluginModel): return ret -class GlancesGrabSensors(object): +class GlancesGrabSensors: """Get sensors stats.""" def __init__(self, sensor_type: Literal[SensorType.FAN_SPEED, SensorType.CPU_TEMP]): diff --git a/glances/plugins/sensors/sensor/glances_batpercent.py b/glances/plugins/sensors/sensor/glances_batpercent.py index 8c280c16..935beae5 100644 --- a/glances/plugins/sensors/sensor/glances_batpercent.py +++ b/glances/plugins/sensors/sensor/glances_batpercent.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -31,7 +30,7 @@ psutil_tag = True try: psutil.sensors_battery() except Exception as e: - logger.error("Cannot grab battery status {}.".format(e)) + logger.error(f"Cannot grab battery status {e}.") psutil_tag = False @@ -43,13 +42,13 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[]) + super().__init__(args=args, config=config, stats_init_value=[]) # Init the sensor class try: self.glances_grab_bat = GlancesGrabBat() except Exception as e: - logger.error("Can not init battery class ({})".format(e)) + logger.error(f"Can not init battery class ({e})") global batinfo_tag global psutil_tag batinfo_tag = False @@ -82,7 +81,7 @@ class PluginModel(GlancesPluginModel): return self.stats -class GlancesGrabBat(object): +class GlancesGrabBat: """Get batteries stats using the batinfo library.""" def __init__(self): diff --git a/glances/plugins/sensors/sensor/glances_hddtemp.py b/glances/plugins/sensors/sensor/glances_hddtemp.py index abcfbb7c..deb8ac89 100644 --- a/glances/plugins/sensors/sensor/glances_hddtemp.py +++ b/glances/plugins/sensors/sensor/glances_hddtemp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -25,7 +24,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[]) + super().__init__(args=args, config=config, stats_init_value=[]) # Init the sensor class hddtemp_host = self.get_conf_value("host", default=["127.0.0.1"])[0] @@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel): return self.stats -class GlancesGrabHDDTemp(object): +class GlancesGrabHDDTemp: """Get hddtemp stats using a socket connection.""" def __init__(self, host='127.0.0.1', port=7634, args=None): @@ -133,7 +132,7 @@ class GlancesGrabHDDTemp(object): break data += received except Exception as e: - logger.debug("Cannot connect to an HDDtemp server ({}:{} => {})".format(self.host, self.port, e)) + logger.debug(f"Cannot connect to an HDDtemp server ({self.host}:{self.port} => {e})") logger.debug("Disable the HDDtemp module. Use the --disable-hddtemp to hide the previous message.") if self.args is not None: self.args.disable_hddtemp = True @@ -141,7 +140,7 @@ class GlancesGrabHDDTemp(object): finally: sck.close() if data != "": - logger.debug("Received data from the HDDtemp server: {}".format(data)) + logger.debug(f"Received data from the HDDtemp server: {data}") return data diff --git a/glances/plugins/smart/__init__.py b/glances/plugins/smart/__init__.py index 88f04320..09367ffa 100644 --- a/glances/plugins/smart/__init__.py +++ b/glances/plugins/smart/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -44,7 +43,7 @@ try: from pySMART import DeviceList except ImportError as e: import_error_tag = True - logger.warning("Missing Python Lib ({}), HDD Smart plugin is disabled".format(e)) + logger.warning(f"Missing Python Lib ({e}), HDD Smart plugin is disabled") else: import_error_tag = False @@ -89,7 +88,7 @@ def get_smart_data(): devlist = DeviceList() except TypeError as e: # Catch error (see #1806) - logger.debug('Smart plugin error - Can not grab device list ({})'.format(e)) + logger.debug(f'Smart plugin error - Can not grab device list ({e})') global import_error_tag import_error_tag = True return stats @@ -97,7 +96,7 @@ def get_smart_data(): for dev in devlist.devices: stats.append( { - 'DeviceName': '{} {}'.format(dev.name, dev.model), + 'DeviceName': f'{dev.name} {dev.model}', } ) for attribute in dev.attributes: @@ -112,7 +111,7 @@ def get_smart_data(): assert num is not None except Exception as e: # we should never get here, but if we do, continue to next iteration and skip this attribute - logger.debug('Smart plugin error - Skip the attribute {} ({})'.format(attribute, e)) + logger.debug(f'Smart plugin error - Skip the attribute {attribute} ({e})') continue stats[-1][num] = attrib_dict @@ -129,7 +128,7 @@ class PluginModel(GlancesPluginModel): disable(args, "smart") logger.debug("Current user is not admin, HDD SMART plugin disabled.") - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) # We want to display the stat in the curse interface self.display_curse = True @@ -172,7 +171,7 @@ class PluginModel(GlancesPluginModel): name_max_width = max_width - 6 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Header diff --git a/glances/plugins/system/__init__.py b/glances/plugins/system/__init__.py index 3cc7a543..ad0d7040 100644 --- a/glances/plugins/system/__init__.py +++ b/glances/plugins/system/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -9,10 +8,10 @@ """System plugin.""" +import builtins import os import platform import re -from io import open from glances.globals import iteritems from glances.logger import logger @@ -92,12 +91,12 @@ def _linux_os_release(): ashtray = {} keys = ['NAME', 'VERSION_ID'] try: - with open(os.path.join('/etc', 'os-release')) as f: + with builtins.open(os.path.join('/etc', 'os-release')) as f: for line in f: for key in keys: if line.startswith(key): ashtray[key] = re.sub(r'^"|"$', '', line.strip().split('=')[1]) - except (OSError, IOError): + except OSError: return pretty_name if ashtray: @@ -117,7 +116,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, fields_description=fields_description) + super().__init__(args=args, config=config, fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True diff --git a/glances/plugins/uptime/__init__.py b/glances/plugins/uptime/__init__.py index 0e3f71eb..5844586b 100644 --- a/glances/plugins/uptime/__init__.py +++ b/glances/plugins/uptime/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -27,7 +26,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) # We want to display the stat in the curse interface self.display_curse = True @@ -83,4 +82,4 @@ class PluginModel(GlancesPluginModel): if not self.stats or self.is_disabled(): return ret - return [self.curse_add_line('Uptime: {}'.format(self.stats))] + return [self.curse_add_line(f'Uptime: {self.stats}')] diff --git a/glances/plugins/version/__init__.py b/glances/plugins/version/__init__.py index 2ed77383..3e2c8fd4 100644 --- a/glances/plugins/version/__init__.py +++ b/glances/plugins/version/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -23,7 +22,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config) + super().__init__(args=args, config=config) self.reset() diff --git a/glances/plugins/wifi/__init__.py b/glances/plugins/wifi/__init__.py index 8f0d26cf..dc6fc5a1 100644 --- a/glances/plugins/wifi/__init__.py +++ b/glances/plugins/wifi/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -29,7 +28,7 @@ WIRELESS_FILE = '/proc/net/wireless' wireless_file_exists = file_exists(WIRELESS_FILE) if not wireless_file_exists: - logger.debug("Wifi plugin is disabled (no %s file found)" % (WIRELESS_FILE)) + logger.debug(f"Wifi plugin is disabled (no {WIRELESS_FILE} file found)") # Fields description # description: human readable description @@ -58,7 +57,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[]) + super().__init__(args=args, config=config, stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True @@ -71,7 +70,7 @@ class PluginModel(GlancesPluginModel): if self._thread is not None: self._thread.stop() # Call the father class - super(PluginModel, self).exit() + super().exit() def get_key(self): """Return the key of the list. @@ -98,7 +97,7 @@ class PluginModel(GlancesPluginModel): if self.input_method == 'local' and wireless_file_exists: # As a backup solution, use the /proc/net/wireless file - with open(WIRELESS_FILE, 'r') as f: + with open(WIRELESS_FILE) as f: # The first two lines are header f.readline() f.readline() @@ -154,7 +153,7 @@ class PluginModel(GlancesPluginModel): def update_views(self): """Update stats views.""" # Call the father's method - super(PluginModel, self).update_views() + super().update_views() # Add specifics information # Alert on quality_level thresholds @@ -175,7 +174,7 @@ class PluginModel(GlancesPluginModel): if_name_max_width = max_width - 5 else: # No max_width defined, return an emptu curse message - logger.debug("No max_width defined for the {} plugin, it will not be displayed.".format(self.plugin_name)) + logger.debug(f"No max_width defined for the {self.plugin_name} plugin, it will not be displayed.") return ret # Build the string message diff --git a/glances/ports_list.py b/glances/ports_list.py index 30f692ab..b0530d2f 100644 --- a/glances/ports_list.py +++ b/glances/ports_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ else: netifaces_tag = False -class GlancesPortsList(object): +class GlancesPortsList: """Manage the ports list for the ports plugin.""" _section = "ports" @@ -46,9 +45,9 @@ class GlancesPortsList(object): if config is None: logger.debug("No configuration file available. Cannot load ports list.") elif not config.has_section(self._section): - logger.debug("No [%s] section in the configuration file. Cannot load ports list." % self._section) + logger.debug(f"No [{self._section}] section in the configuration file. Cannot load ports list.") else: - logger.debug("Start reading the [%s] section in the configuration file" % self._section) + logger.debug(f"Start reading the [{self._section}] section in the configuration file") refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh)) timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout)) @@ -68,26 +67,26 @@ class GlancesPortsList(object): new_port['timeout'] = timeout new_port['status'] = None new_port['rtt_warning'] = None - new_port['indice'] = str('port_0') - logger.debug("Add default gateway %s to the static list" % (new_port['host'])) + new_port['indice'] = 'port_0' + logger.debug("Add default gateway {} to the static list".format(new_port['host'])) ports_list.append(new_port) # Read the scan list for i in range(1, 256): new_port = {} - postfix = 'port_%s_' % str(i) + postfix = f'port_{str(i)}_' # Read mandatory configuration key: host - new_port['host'] = config.get_value(self._section, '%s%s' % (postfix, 'host')) + new_port['host'] = config.get_value(self._section, '{}{}'.format(postfix, 'host')) if new_port['host'] is None: continue # Read optionals configuration keys # Port is set to 0 by default. 0 mean ICMP check instead of TCP check - new_port['port'] = config.get_value(self._section, '%s%s' % (postfix, 'port'), 0) + new_port['port'] = config.get_value(self._section, '{}{}'.format(postfix, 'port'), 0) new_port['description'] = config.get_value( - self._section, '%sdescription' % postfix, default="%s:%s" % (new_port['host'], new_port['port']) + self._section, f'{postfix}description', default="{}:{}".format(new_port['host'], new_port['port']) ) # Default status @@ -97,10 +96,10 @@ class GlancesPortsList(object): new_port['refresh'] = refresh # Timeout in second - new_port['timeout'] = int(config.get_value(self._section, '%stimeout' % postfix, default=timeout)) + new_port['timeout'] = int(config.get_value(self._section, f'{postfix}timeout', default=timeout)) # RTT warning - new_port['rtt_warning'] = config.get_value(self._section, '%srtt_warning' % postfix, default=None) + new_port['rtt_warning'] = config.get_value(self._section, f'{postfix}rtt_warning', default=None) if new_port['rtt_warning'] is not None: # Convert to second new_port['rtt_warning'] = int(new_port['rtt_warning']) / 1000.0 @@ -109,11 +108,11 @@ class GlancesPortsList(object): new_port['indice'] = 'port_' + str(i) # Add the server to the list - logger.debug("Add port %s:%s to the static list" % (new_port['host'], new_port['port'])) + logger.debug("Add port {}:{} to the static list".format(new_port['host'], new_port['port'])) ports_list.append(new_port) # Ports list loaded - logger.debug("Ports list loaded: %s" % ports_list) + logger.debug(f"Ports list loaded: {ports_list}") return ports_list diff --git a/glances/processes.py b/glances/processes.py index fea4c004..0b507596 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -34,7 +33,7 @@ sort_for_human = { } -class GlancesProcesses(object): +class GlancesProcesses: """Get processed stats using the psutil library.""" def __init__(self, cache_timeout=60): @@ -83,7 +82,7 @@ class GlancesProcesses(object): p = psutil.Process() p.io_counters() except Exception as e: - logger.warning('PsUtil can not grab processes io_counters ({})'.format(e)) + logger.warning(f'PsUtil can not grab processes io_counters ({e})') self.disable_io_counters = True else: logger.debug('PsUtil can grab processes io_counters') @@ -94,7 +93,7 @@ class GlancesProcesses(object): p = psutil.Process() p.gids() except Exception as e: - logger.warning('PsUtil can not grab processes gids ({})'.format(e)) + logger.warning(f'PsUtil can not grab processes gids ({e})') self.disable_gids = True else: logger.debug('PsUtil can grab processes gids') @@ -183,7 +182,7 @@ class GlancesProcesses(object): try: with open('/proc/sys/kernel/pid_max', 'rb') as f: return int(f.read()) - except (OSError, IOError): + except OSError: return None else: return None @@ -310,7 +309,7 @@ class GlancesProcesses(object): # Get number of TCP and UDP network connections for the selected process ret['tcp'], ret['udp'] = self.__get_extended_connections(selected_process) except (psutil.NoSuchProcess, ValueError, AttributeError) as e: - logger.error('Can not grab extended stats ({})'.format(e)) + logger.error(f'Can not grab extended stats ({e})') self.extended_process = None ret['extended_stats'] = False else: @@ -595,11 +594,9 @@ class GlancesProcesses(object): p = psutil.Process(pid) try: p.nice(p.nice() - 1) - logger.info('Set nice level of process {} to {} (higher the priority)'.format(pid, p.nice())) + logger.info(f'Set nice level of process {pid} to {p.nice()} (higher the priority)') except psutil.AccessDenied: - logger.warning( - 'Can not decrease (higher the priority) the nice level of process {} (access denied)'.format(pid) - ) + logger.warning(f'Can not decrease (higher the priority) the nice level of process {pid} (access denied)') def nice_increase(self, pid): """Increase nice level @@ -608,17 +605,15 @@ class GlancesProcesses(object): p = psutil.Process(pid) try: p.nice(p.nice() + 1) - logger.info('Set nice level of process {} to {} (lower the priority)'.format(pid, p.nice())) + logger.info(f'Set nice level of process {pid} to {p.nice()} (lower the priority)') except psutil.AccessDenied: - logger.warning( - 'Can not increase (lower the priority) the nice level of process {} (access denied)'.format(pid) - ) + logger.warning(f'Can not increase (lower the priority) the nice level of process {pid} (access denied)') def kill(self, pid, timeout=3): """Kill process with pid""" assert pid != os.getpid(), "Glances can kill itself..." p = psutil.Process(pid) - logger.debug('Send kill signal to process: {}'.format(p)) + logger.debug(f'Send kill signal to process: {p}') p.kill() return p.wait(timeout) diff --git a/glances/programs.py b/glances/programs.py index f3fcefcc..60e19813 100644 --- a/glances/programs.py +++ b/glances/programs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # diff --git a/glances/secure.py b/glances/secure.py index 03745d3a..30ef62ec 100644 --- a/glances/secure.py +++ b/glances/secure.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -39,7 +38,7 @@ def __secure_popen(cmd): # Split by redirection '>' cmd_split_redirect = cmd.split('>') if len(cmd_split_redirect) > 2: - return 'Glances error: Only one file redirection allowed ({})'.format(cmd) + return f'Glances error: Only one file redirection allowed ({cmd})' if len(cmd_split_redirect) == 2: stdout_redirect = cmd_split_redirect[1].strip() cmd = cmd_split_redirect[0] diff --git a/glances/server.py b/glances/server.py index 55b48831..babcb528 100644 --- a/glances/server.py +++ b/glances/server.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -21,7 +20,7 @@ from glances.stats_server import GlancesStatsServer from glances.timer import Timer -class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, object): +class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler): """Main XML-RPC handler.""" rpc_paths = ('/RPC2',) @@ -30,7 +29,7 @@ class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, object): # Hack to add a specific header # Thk to: https://gist.github.com/rca/4063325 self.send_my_headers() - super(GlancesXMLRPCHandler, self).end_headers() + super().end_headers() def send_my_headers(self): # Specific header is here (solved the issue #227) @@ -84,7 +83,7 @@ class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, object): pass -class GlancesXMLRPCServer(SimpleXMLRPCServer, object): +class GlancesXMLRPCServer(SimpleXMLRPCServer): """Init a SimpleXMLRPCServer instance (IPv6-ready).""" finished = False @@ -95,11 +94,11 @@ class GlancesXMLRPCServer(SimpleXMLRPCServer, object): self.config = config try: self.address_family = socket.getaddrinfo(bind_address, bind_port)[0][0] - except socket.error as e: - logger.error("Couldn't open socket: {}".format(e)) + except OSError as e: + logger.error(f"Couldn't open socket: {e}") sys.exit(1) - super(GlancesXMLRPCServer, self).__init__((bind_address, bind_port), requestHandler) + super().__init__((bind_address, bind_port), requestHandler) def end(self): """Stop the server""" @@ -112,7 +111,7 @@ class GlancesXMLRPCServer(SimpleXMLRPCServer, object): self.handle_request() -class GlancesInstance(object): +class GlancesInstance: """All the methods of this class are published as XML-RPC methods.""" def __init__(self, config=None, args=None): @@ -176,7 +175,7 @@ class GlancesInstance(object): raise AttributeError(item) -class GlancesServer(object): +class GlancesServer: """This class creates and manages the TCP server.""" def __init__(self, requestHandler=GlancesXMLRPCHandler, config=None, args=None): @@ -187,10 +186,10 @@ class GlancesServer(object): try: self.server = GlancesXMLRPCServer(args.bind_address, args.port, requestHandler, config=config) except Exception as e: - logger.critical("Cannot start Glances server: {}".format(e)) + logger.critical(f"Cannot start Glances server: {e}") sys.exit(2) else: - print('Glances XML-RPC server is running on {}:{}'.format(args.bind_address, args.port)) + print(f'Glances XML-RPC server is running on {args.bind_address}:{args.port}') # The users dict # username / password couple diff --git a/glances/snmp.py b/glances/snmp.py index debfcdb6..f5fbb1e1 100644 --- a/glances/snmp.py +++ b/glances/snmp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -19,11 +18,11 @@ except ImportError: sys.exit(2) -class GlancesSNMPClient(object): +class GlancesSNMPClient: """SNMP client class (based on pysnmp library).""" def __init__(self, host='localhost', port=161, version='2c', community='public', user='private', auth=''): - super(GlancesSNMPClient, self).__init__() + super().__init__() self.cmdGen = cmdgen.CommandGenerator() self.version = version diff --git a/glances/standalone.py b/glances/standalone.py index ae9090c4..ce762069 100644 --- a/glances/standalone.py +++ b/glances/standalone.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -26,7 +25,7 @@ from glances.stats import GlancesStats from glances.timer import Counter -class GlancesStandalone(object): +class GlancesStandalone: """This class creates and manages the Glances standalone session.""" def __init__(self, config=None, args=None): @@ -41,7 +40,7 @@ class GlancesStandalone(object): start_duration = Counter() start_duration.reset() self.stats = GlancesStats(config=config, args=args) - logger.debug("Plugins initialisation duration: {} seconds".format(start_duration.get())) + logger.debug(f"Plugins initialisation duration: {start_duration.get()} seconds") # Modules (plugins and exporters) are loaded at this point # Glances can display the list if asked... @@ -62,11 +61,11 @@ class GlancesStandalone(object): # Manage optional process filter if args.process_filter is not None: - logger.info("Process filter is set to: {}".format(args.process_filter)) + logger.info(f"Process filter is set to: {args.process_filter}") glances_processes.process_filter = args.process_filter if (args.export or args.stdout) and args.export_process_filter is not None: - logger.info("Export process filter is set to: {}".format(args.export_process_filter)) + logger.info(f"Export process filter is set to: {args.export_process_filter}") glances_processes.export_process_filter = args.export_process_filter if (not WINDOWS) and args.no_kernel_threads: @@ -76,7 +75,7 @@ class GlancesStandalone(object): # Initial system information update start_duration.reset() self.stats.update() - logger.debug("First stats update duration: {} seconds".format(start_duration.get())) + logger.debug(f"First stats update duration: {start_duration.get()} seconds") if self.quiet: logger.info("Quiet mode is ON, nothing will be displayed") @@ -91,15 +90,15 @@ class GlancesStandalone(object): # Init screen self.screen = GlancesStdoutApiDoc(config=config, args=args) elif args.stdout: - logger.info("Stdout mode is ON, following stats will be displayed: {}".format(args.stdout)) + logger.info(f"Stdout mode is ON, following stats will be displayed: {args.stdout}") # Init screen self.screen = GlancesStdout(config=config, args=args) elif args.stdout_json: - logger.info("Stdout JSON mode is ON, following stats will be displayed: {}".format(args.stdout_json)) + logger.info(f"Stdout JSON mode is ON, following stats will be displayed: {args.stdout_json}") # Init screen self.screen = GlancesStdoutJson(config=config, args=args) elif args.stdout_csv: - logger.info("Stdout CSV mode is ON, following stats will be displayed: {}".format(args.stdout_csv)) + logger.info(f"Stdout CSV mode is ON, following stats will be displayed: {args.stdout_csv}") # Init screen self.screen = GlancesStdoutCsv(config=config, args=args) else: @@ -143,7 +142,7 @@ class GlancesStandalone(object): # Start a counter used to compute the time needed counter = Counter() self.stats.update() - logger.debug('Stats updated duration: {} seconds'.format(counter.get())) + logger.debug(f'Stats updated duration: {counter.get()} seconds') # Patch for issue1326 to avoid < 0 refresh adapted_refresh = (self.refresh_time - counter.get()) if (self.refresh_time - counter.get()) > 0 else 0 @@ -155,7 +154,7 @@ class GlancesStandalone(object): # has been pressed. counter_display = Counter() ret = not self.screen.update(self.stats, duration=adapted_refresh) - logger.debug('Stats display duration: {} seconds'.format(counter_display.get() - adapted_refresh)) + logger.debug(f'Stats display duration: {counter_display.get() - adapted_refresh} seconds') else: # Nothing is displayed # Break should be done via a signal (CTRL-C) @@ -166,7 +165,7 @@ class GlancesStandalone(object): # Start a counter used to compute the time needed counter_export = Counter() self.stats.export(self.stats) - logger.debug('Stats exported duration: {} seconds'.format(counter_export.get())) + logger.debug(f'Stats exported duration: {counter_export.get()} seconds') return ret @@ -196,11 +195,9 @@ class GlancesStandalone(object): # Check Glances version versus PyPI one if self.outdated.is_outdated(): - print( - "You are using Glances version {}, however version {} is available.".format( - self.outdated.installed_version(), self.outdated.latest_version() - ) - ) + latest_version = self.outdated.latest_version() + installed_version = self.outdated.installed_version() + print(f"You are using Glances version {installed_version}, however version {latest_version} is available.") print("You should consider upgrading using: pip install --upgrade glances") print("Disable this warning temporarily using: glances --disable-check-update") print( diff --git a/glances/static_list.py b/glances/static_list.py index b293b40f..2ff6ea81 100644 --- a/glances/static_list.py +++ b/glances/static_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -14,7 +13,7 @@ from socket import gaierror, gethostbyname from glances.logger import logger -class GlancesStaticServer(object): +class GlancesStaticServer: """Manage the static servers list for the client browser.""" _section = "serverlist" @@ -32,15 +31,15 @@ class GlancesStaticServer(object): if config is None: logger.debug("No configuration file available. Cannot load server list.") elif not config.has_section(self._section): - logger.warning("No [%s] section in the configuration file. Cannot load server list." % self._section) + logger.warning(f"No [{self._section}] section in the configuration file. Cannot load server list.") else: - logger.info("Start reading the [%s] section in the configuration file" % self._section) + logger.info(f"Start reading the [{self._section}] section in the configuration file") for i in range(1, 256): new_server = {} - postfix = 'server_%s_' % str(i) + postfix = f'server_{str(i)}_' # Read the server name (mandatory) for s in ['name', 'port', 'alias']: - new_server[s] = config.get_value(self._section, '%s%s' % (postfix, s)) + new_server[s] = config.get_value(self._section, f'{postfix}{s}') if new_server['name'] is not None: # Manage optional information if new_server['port'] is None: @@ -51,7 +50,7 @@ class GlancesStaticServer(object): try: new_server['ip'] = gethostbyname(new_server['name']) except gaierror as e: - logger.error("Cannot get IP address for server %s (%s)" % (new_server['name'], e)) + logger.error("Cannot get IP address for server {} ({})".format(new_server['name'], e)) continue new_server['key'] = new_server['name'] + ':' + new_server['port'] @@ -62,12 +61,12 @@ class GlancesStaticServer(object): new_server['type'] = 'STATIC' # Add the server to the list - logger.debug("Add server %s to the static list" % new_server['name']) + logger.debug("Add server {} to the static list".format(new_server['name'])) server_list.append(new_server) # Server list loaded - logger.info("%s server(s) loaded from the configuration file" % len(server_list)) - logger.debug("Static server list: %s" % server_list) + logger.info(f"{len(server_list)} server(s) loaded from the configuration file") + logger.debug(f"Static server list: {server_list}") return server_list diff --git a/glances/stats.py b/glances/stats.py index 0f55990f..99eae439 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -22,7 +21,7 @@ from glances.logger import logger from glances.timer import Counter -class GlancesStats(object): +class GlancesStats: """This class stores, updates and gives stats.""" # Script header constant @@ -104,7 +103,7 @@ class GlancesStats(object): except Exception as e: # If a plugin can not be loaded, display a critical message # on the console but do not crash - logger.critical("Error while initializing the {} plugin ({})".format(plugin_path, e)) + logger.critical(f"Error while initializing the {plugin_path} plugin ({e})") logger.error(traceback.format_exc()) # An error occurred, disable the plugin if args is not None: @@ -128,10 +127,10 @@ class GlancesStats(object): # Load the plugin start_duration.reset() self._load_plugin(os.path.basename(item), args=args, config=self.config) - logger.debug("Plugin {} started in {} seconds".format(item, start_duration.get())) + logger.debug(f"Plugin {item} started in {start_duration.get()} seconds") # Log plugins list - logger.debug("Active plugins list: {}".format(self.getPluginsList())) + logger.debug(f"Active plugins list: {self.getPluginsList()}") def load_additional_plugins(self, args=None, config=None): """Load additional plugins if defined""" @@ -174,11 +173,11 @@ class GlancesStats(object): try: _mod_loaded = import_module(plugin + '.model') self._plugins[plugin] = _mod_loaded.PluginModel(args=args, config=config) - logger.debug("Plugin {} started in {} seconds".format(plugin, start_duration.get())) + logger.debug(f"Plugin {plugin} started in {start_duration.get()} seconds") except Exception as e: # If a plugin can not be loaded, display a critical message # on the console but do not crash - logger.critical("Error while initializing the {} plugin ({})".format(plugin, e)) + logger.critical(f"Error while initializing the {plugin} plugin ({e})") logger.error(traceback.format_exc()) # An error occurred, disable the plugin if args: @@ -186,7 +185,7 @@ class GlancesStats(object): sys.path = _sys_path # Log plugins list - logger.debug("Active additional plugins list: {}".format(self.getPluginsList())) + logger.debug(f"Active additional plugins list: {self.getPluginsList()}") def load_exports(self, args=None): """Load all exporters in the 'exports' folder.""" @@ -218,10 +217,10 @@ class GlancesStats(object): else: # Add the exporter name to the available exporters dictionary self._exports_all[exporter_name] = exporter_name - logger.debug("Exporter {} started in {} seconds".format(exporter_name, start_duration.get())) + logger.debug(f"Exporter {exporter_name} started in {start_duration.get()} seconds") # Log plugins list - logger.debug("Active exports modules list: {}".format(self.getExportsList())) + logger.debug(f"Active exports modules list: {self.getExportsList()}") return True def getPluginsList(self, enable=True): @@ -288,7 +287,7 @@ class GlancesStats(object): input_stats = input_stats or {} for e in self.getExportsList(enable=True): - logger.debug("Export stats using the %s module" % e) + logger.debug(f"Export stats using the {e} module") thread = threading.Thread(target=self._exports[e].update, args=(input_stats,)) thread.start() diff --git a/glances/stats_client.py b/glances/stats_client.py index 15ad30f3..02d13f42 100644 --- a/glances/stats_client.py +++ b/glances/stats_client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -21,7 +20,7 @@ class GlancesStatsClient(GlancesStats): def __init__(self, config=None, args=None): """Init the GlancesStatsClient class.""" - super(GlancesStatsClient, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Init the configuration self.config = config @@ -38,15 +37,13 @@ class GlancesStatsClient(GlancesStats): plugin = __import__(header + item) except ImportError: # Server plugin can not be imported from the client side - logger.error( - "Can not import {} plugin. Please upgrade your Glances client/server version.".format(item) - ) + logger.error(f"Can not import {item} plugin. Please upgrade your Glances client/server version.") else: # Add the plugin to the dictionary # The key is the plugin name # for example, the file glances_xxx.py # generate self._plugins_list["xxx"] = ... - logger.debug("Server uses {} plugin".format(item)) + logger.debug(f"Server uses {item} plugin") self._plugins[item] = plugin.Plugin(args=self.args) # Restoring system path sys.path = sys_path diff --git a/glances/stats_client_snmp.py b/glances/stats_client_snmp.py index 5007656a..bb73a3e5 100644 --- a/glances/stats_client_snmp.py +++ b/glances/stats_client_snmp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -31,7 +30,7 @@ class GlancesStatsClientSNMP(GlancesStats): """This class stores, updates and gives stats for the SNMP client.""" def __init__(self, config=None, args=None): - super(GlancesStatsClientSNMP, self).__init__() + super().__init__() # Init the configuration self.config = config @@ -67,7 +66,7 @@ class GlancesStatsClientSNMP(GlancesStats): oid_os_name = snmp_client.get_by_oid("1.3.6.1.2.1.1.1.0") try: self.system_name = self.get_system_name(oid_os_name['1.3.6.1.2.1.1.1.0']) - logger.info("SNMP system name detected: {}".format(self.system_name)) + logger.info(f"SNMP system name detected: {self.system_name}") except KeyError: self.system_name = None logger.warning("Cannot detect SNMP system name") @@ -106,7 +105,7 @@ class GlancesStatsClientSNMP(GlancesStats): try: self._plugins[p].update() except Exception as e: - logger.error("Update {} failed: {}".format(p, e)) + logger.error(f"Update {p} failed: {e}") else: # ... the history self._plugins[p].update_stats_history() diff --git a/glances/stats_server.py b/glances/stats_server.py index 684bbcf6..ada4ed2c 100644 --- a/glances/stats_server.py +++ b/glances/stats_server.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -20,7 +19,7 @@ class GlancesStatsServer(GlancesStats): def __init__(self, config=None, args=None): # Init the stats - super(GlancesStatsServer, self).__init__(config=config, args=args) + super().__init__(config=config, args=args) # Init the all_stats dict used by the server # all_stats is a dict of dicts filled by the server @@ -34,7 +33,7 @@ class GlancesStatsServer(GlancesStats): input_stats = input_stats or {} # Force update of all the stats - super(GlancesStatsServer, self).update() + super().update() # Disable the extended processes stats because it cause an high CPU load self._plugins['processcount'].disable_extended() diff --git a/glances/thresholds.py b/glances/thresholds.py index a7624450..782a0d13 100644 --- a/glances/thresholds.py +++ b/glances/thresholds.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -15,7 +14,7 @@ import sys from functools import total_ordering -class GlancesThresholds(object): +class GlancesThresholds: """Class to manage thresholds dict for all Glances plugins: key: Glances stats (example: cpu_user) @@ -56,7 +55,7 @@ glances_thresholds = GlancesThresholds() @total_ordering -class _GlancesThreshold(object): +class _GlancesThreshold: """Father class for all other Thresholds""" def description(self): diff --git a/glances/timer.py b/glances/timer.py index 030558cb..8120cf4f 100644 --- a/glances/timer.py +++ b/glances/timer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -30,7 +29,7 @@ def getTimeSinceLastUpdate(IOType): return time_since_update -class Timer(object): +class Timer: """The timer class. A simple chronometer.""" def __init__(self, duration): @@ -55,7 +54,7 @@ class Timer(object): return time() > self.target -class Counter(object): +class Counter: """The counter class.""" def __init__(self): diff --git a/glances/web_list.py b/glances/web_list.py index 7ffe871c..e50eb75b 100644 --- a/glances/web_list.py +++ b/glances/web_list.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -13,7 +12,7 @@ from glances.globals import urlparse from glances.logger import logger -class GlancesWebList(object): +class GlancesWebList: """Manage the Web/Url list for the ports plugin.""" _section = "ports" @@ -36,9 +35,9 @@ class GlancesWebList(object): if config is None: logger.debug("No configuration file available. Cannot load ports list.") elif not config.has_section(self._section): - logger.debug("No [%s] section in the configuration file. Cannot load ports list." % self._section) + logger.debug(f"No [{self._section}] section in the configuration file. Cannot load ports list.") else: - logger.debug("Start reading the [%s] section in the configuration file" % self._section) + logger.debug(f"Start reading the [{self._section}] section in the configuration file") refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh)) timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout)) @@ -46,23 +45,23 @@ class GlancesWebList(object): # Read the web/url list for i in range(1, 256): new_web = {} - postfix = 'web_%s_' % str(i) + postfix = f'web_{str(i)}_' # Read mandatory configuration key: host - new_web['url'] = config.get_value(self._section, '%s%s' % (postfix, 'url')) + new_web['url'] = config.get_value(self._section, '{}{}'.format(postfix, 'url')) if new_web['url'] is None: continue url_parse = urlparse(new_web['url']) if not bool(url_parse.scheme) or not bool(url_parse.netloc): logger.error( - 'Bad URL (%s) in the [%s] section of configuration file.' % (new_web['url'], self._section) + 'Bad URL ({}) in the [{}] section of configuration file.'.format(new_web['url'], self._section) ) continue # Read optionals configuration keys # Default description is the URL without the http:// new_web['description'] = config.get_value( - self._section, '%sdescription' % postfix, default="%s" % url_parse.netloc + self._section, f'{postfix}description', default=f"{url_parse.netloc}" ) # Default status @@ -73,10 +72,10 @@ class GlancesWebList(object): new_web['refresh'] = refresh # Timeout in second - new_web['timeout'] = int(config.get_value(self._section, '%stimeout' % postfix, default=timeout)) + new_web['timeout'] = int(config.get_value(self._section, f'{postfix}timeout', default=timeout)) # RTT warning - new_web['rtt_warning'] = config.get_value(self._section, '%srtt_warning' % postfix, default=None) + new_web['rtt_warning'] = config.get_value(self._section, f'{postfix}rtt_warning', default=None) if new_web['rtt_warning'] is not None: # Convert to second new_web['rtt_warning'] = int(new_web['rtt_warning']) / 1000.0 @@ -85,11 +84,11 @@ class GlancesWebList(object): new_web['indice'] = 'web_' + str(i) # ssl_verify - new_web['ssl_verify'] = config.get_value(self._section, '%sssl_verify' % postfix, default=True) + new_web['ssl_verify'] = config.get_value(self._section, f'{postfix}ssl_verify', default=True) # Proxy - http_proxy = config.get_value(self._section, '%shttp_proxy' % postfix, default=None) + http_proxy = config.get_value(self._section, f'{postfix}http_proxy', default=None) - https_proxy = config.get_value(self._section, '%shttps_proxy' % postfix, default=None) + https_proxy = config.get_value(self._section, f'{postfix}https_proxy', default=None) if https_proxy is None and http_proxy is None: new_web['proxies'] = None @@ -97,11 +96,11 @@ class GlancesWebList(object): new_web['proxies'] = {'http': http_proxy, 'https': https_proxy} # Add the server to the list - logger.debug("Add Web URL %s to the static list" % new_web['url']) + logger.debug("Add Web URL {} to the static list".format(new_web['url'])) web_list.append(new_web) # Ports list loaded - logger.debug("Web list loaded: %s" % web_list) + logger.debug(f"Web list loaded: {web_list}") return web_list diff --git a/glances/webserver.py b/glances/webserver.py index 859ce820..f56e9256 100644 --- a/glances/webserver.py +++ b/glances/webserver.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # This file is part of Glances. # @@ -15,7 +14,7 @@ from glances.processes import glances_processes from glances.stats import GlancesStats -class GlancesWebServer(object): +class GlancesWebServer: """This class creates and manages the Glances Web server session.""" def __init__(self, config=None, args=None): diff --git a/pyproject.toml b/pyproject.toml index feb629db..7a1f3608 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ select = [ "I", # isort # "N", # pep8-naming "W", # pycodestyle -# "UP", # pyupgrde + "UP", # pyupgrde # "C4", # flake8-comprehensions "RET", # flake8-return # "FBT", # flake8-boolean-trap diff --git a/run.py b/run.py index a5db19e7..fe84f648 100755 --- a/run.py +++ b/run.py @@ -1,5 +1,4 @@ #!/usr/bin/python -# -*- coding: utf-8 -*- import re import sys diff --git a/setup.py b/setup.py index e220b2f6..d095cb84 100755 --- a/setup.py +++ b/setup.py @@ -1,32 +1,27 @@ #!/usr/bin/env python +import builtins import glob import os import re import sys -from io import open from setuptools import Command, setup -# Predication warning -# Glances version 4 will only be compatible with Python 3.7 and above -if sys.version_info < (3, 7): - print('WARNING: Glances version 4 will only be compatible with Python 3.7 and above.') - -if sys.version_info < (3, 8): +if not (sys.version_info >= (3, 8)): print('Glances requires at least Python 3.8 to run.') sys.exit(1) # Global functions ################## -with open(os.path.join('glances', '__init__.py'), encoding='utf-8') as f: +with builtins.open(os.path.join('glances', '__init__.py'), encoding='utf-8') as f: version = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", f.read(), re.M).group(1) if not version: raise RuntimeError('Cannot find Glances version information.') -with open('README.rst', encoding='utf-8') as f: +with builtins.open('README.rst', encoding='utf-8') as f: long_description = f.read() @@ -40,7 +35,7 @@ def get_data_files(): ] -with open('requirements.txt') as f: +with builtins.open('requirements.txt') as f: required = f.read().splitlines() diff --git a/unittest-core.py b/unittest-core.py index 9383883c..6626d6a4 100755 --- a/unittest-core.py +++ b/unittest-core.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Glances - An eye on your system # @@ -11,15 +10,9 @@ """Glances unitary tests suite.""" import json -import sys import time import unittest -# Check Python version -if sys.version_info < (3, 8): - print('Glances requires at least Python 3.8 to run.') - sys.exit(1) - from glances import __version__ from glances.events_list import GlancesEventsList from glances.filter import GlancesFilter, GlancesFilterList @@ -51,7 +44,7 @@ stats = GlancesStats(config=test_config, args=test_args) # Unitest class # ============== -print('Unitary tests for Glances %s' % __version__) +print(f'Unitary tests for Glances {__version__}') class TestGlances(unittest.TestCase): @@ -186,13 +179,13 @@ class TestGlances(unittest.TestCase): try: stats.update() except Exception as e: - print('ERROR: Stats update failed: %s' % e) + print(f'ERROR: Stats update failed: {e}') self.assertTrue(False) time.sleep(1) try: stats.update() except Exception as e: - print('ERROR: Stats update failed: %s' % e) + print(f'ERROR: Stats update failed: {e}') self.assertTrue(False) self.assertTrue(True) @@ -200,7 +193,7 @@ class TestGlances(unittest.TestCase): def test_001_plugins(self): """Check mandatory plugins.""" plugins_to_check = ['system', 'cpu', 'load', 'mem', 'memswap', 'network', 'diskio', 'fs'] - print('INFO: [TEST_001] Check the mandatory plugins list: %s' % ', '.join(plugins_to_check)) + print('INFO: [TEST_001] Check the mandatory plugins list: {}'.format(', '.join(plugins_to_check))) plugins_list = stats.getPluginsList() for plugin in plugins_to_check: self.assertTrue(plugin in plugins_list) @@ -208,38 +201,38 @@ class TestGlances(unittest.TestCase): def test_002_system(self): """Check SYSTEM plugin.""" stats_to_check = ['hostname', 'os_name'] - print('INFO: [TEST_002] Check SYSTEM stats: %s' % ', '.join(stats_to_check)) + print('INFO: [TEST_002] Check SYSTEM stats: {}'.format(', '.join(stats_to_check))) stats_grab = stats.get_plugin('system').get_raw() for stat in stats_to_check: # Check that the key exist - self.assertTrue(stat in stats_grab, msg='Cannot find key: %s' % stat) - print('INFO: SYSTEM stats: %s' % stats_grab) + self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}') + print(f'INFO: SYSTEM stats: {stats_grab}') def test_003_cpu(self): """Check CPU plugin.""" stats_to_check = ['system', 'user', 'idle'] - print('INFO: [TEST_003] Check mandatory CPU stats: %s' % ', '.join(stats_to_check)) + print('INFO: [TEST_003] Check mandatory CPU stats: {}'.format(', '.join(stats_to_check))) stats_grab = stats.get_plugin('cpu').get_raw() for stat in stats_to_check: # Check that the key exist - self.assertTrue(stat in stats_grab, msg='Cannot find key: %s' % stat) + self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}') # Check that % is > 0 and < 100 self.assertGreaterEqual(stats_grab[stat], 0) self.assertLessEqual(stats_grab[stat], 100) - print('INFO: CPU stats: %s' % stats_grab) + print(f'INFO: CPU stats: {stats_grab}') @unittest.skipIf(WINDOWS, "Load average not available on Windows") def test_004_load(self): """Check LOAD plugin.""" stats_to_check = ['cpucore', 'min1', 'min5', 'min15'] - print('INFO: [TEST_004] Check LOAD stats: %s' % ', '.join(stats_to_check)) + print('INFO: [TEST_004] Check LOAD stats: {}'.format(', '.join(stats_to_check))) stats_grab = stats.get_plugin('load').get_raw() for stat in stats_to_check: # Check that the key exist - self.assertTrue(stat in stats_grab, msg='Cannot find key: %s' % stat) + self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}') # Check that % is > 0 self.assertGreaterEqual(stats_grab[stat], 0) - print('INFO: LOAD stats: %s' % stats_grab) + print(f'INFO: LOAD stats: {stats_grab}') def test_005_mem(self): """Check MEM plugin.""" @@ -249,36 +242,36 @@ class TestGlances(unittest.TestCase): stats_grab = stats.get_plugin('mem').get_raw() for stat in stats_to_check: # Check that the key exist - self.assertTrue(stat in stats_grab, msg='Cannot find key: %s' % stat) + self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}') # Check that % is > 0 self.assertGreaterEqual(stats_grab[stat], 0) - print('INFO: MEM stats: %s' % stats_grab) + print(f'INFO: MEM stats: {stats_grab}') def test_006_memswap(self): """Check MEMSWAP plugin.""" stats_to_check = ['used', 'free', 'total'] - print('INFO: [TEST_006] Check MEMSWAP stats: %s' % ', '.join(stats_to_check)) + print('INFO: [TEST_006] Check MEMSWAP stats: {}'.format(', '.join(stats_to_check))) stats_grab = stats.get_plugin('memswap').get_raw() for stat in stats_to_check: # Check that the key exist - self.assertTrue(stat in stats_grab, msg='Cannot find key: %s' % stat) + self.assertTrue(stat in stats_grab, msg=f'Cannot find key: {stat}') # Check that % is > 0 self.assertGreaterEqual(stats_grab[stat], 0) - print('INFO: MEMSWAP stats: %s' % stats_grab) + print(f'INFO: MEMSWAP stats: {stats_grab}') def test_007_network(self): """Check NETWORK plugin.""" print('INFO: [TEST_007] Check NETWORK stats') stats_grab = stats.get_plugin('network').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='Network stats is not a list') - print('INFO: NETWORK stats: %s' % stats_grab) + print(f'INFO: NETWORK stats: {stats_grab}') def test_008_diskio(self): """Check DISKIO plugin.""" print('INFO: [TEST_008] Check DISKIO stats') stats_grab = stats.get_plugin('diskio').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='DiskIO stats is not a list') - print('INFO: diskio stats: %s' % stats_grab) + print(f'INFO: diskio stats: {stats_grab}') def test_009_fs(self): """Check File System plugin.""" @@ -286,7 +279,7 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_009] Check FS stats') stats_grab = stats.get_plugin('fs').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='FileSystem stats is not a list') - print('INFO: FS stats: %s' % stats_grab) + print(f'INFO: FS stats: {stats_grab}') def test_010_processes(self): """Check Process plugin.""" @@ -295,10 +288,10 @@ class TestGlances(unittest.TestCase): stats_grab = stats.get_plugin('processcount').get_raw() # total = stats_grab['total'] self.assertTrue(isinstance(stats_grab, dict), msg='Process count stats is not a dict') - print('INFO: PROCESS count stats: %s' % stats_grab) + print(f'INFO: PROCESS count stats: {stats_grab}') stats_grab = stats.get_plugin('processlist').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='Process count stats is not a list') - print('INFO: PROCESS list stats: %s items in the list' % len(stats_grab)) + print(f'INFO: PROCESS list stats: {len(stats_grab)} items in the list') # Check if number of processes in the list equal counter # self.assertEqual(total, len(stats_grab)) @@ -308,14 +301,14 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_011] Check FOLDER stats') stats_grab = stats.get_plugin('folders').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='Folders stats is not a list') - print('INFO: Folders stats: %s' % stats_grab) + print(f'INFO: Folders stats: {stats_grab}') def test_012_ip(self): """Check IP plugin.""" print('INFO: [TEST_012] Check IP stats') stats_grab = stats.get_plugin('ip').get_raw() self.assertTrue(isinstance(stats_grab, dict), msg='IP stats is not a dict') - print('INFO: IP stats: %s' % stats_grab) + print(f'INFO: IP stats: {stats_grab}') @unittest.skipIf(not LINUX, "IRQs available only on Linux") def test_013_irq(self): @@ -323,7 +316,7 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_013] Check IRQ stats') stats_grab = stats.get_plugin('irq').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='IRQ stats is not a list') - print('INFO: IRQ stats: %s' % stats_grab) + print(f'INFO: IRQ stats: {stats_grab}') @unittest.skipIf(not LINUX, "GPU available only on Linux") def test_014_gpu(self): @@ -331,7 +324,7 @@ class TestGlances(unittest.TestCase): print('INFO: [TEST_014] Check GPU stats') stats_grab = stats.get_plugin('gpu').get_raw() self.assertTrue(isinstance(stats_grab, list), msg='GPU stats is not a list') - print('INFO: GPU stats: %s' % stats_grab) + print(f'INFO: GPU stats: {stats_grab}') def test_015_sorted_stats(self): """Check sorted stats method.""" @@ -384,7 +377,7 @@ class TestGlances(unittest.TestCase): return stat = 'DeviceName' - print('INFO: [TEST_017] Check SMART stats: {}'.format(stat)) + print(f'INFO: [TEST_017] Check SMART stats: {stat}') stats_grab = stats.get_plugin('smart').get_raw() if not is_admin(): print("INFO: Not admin, SMART list should be empty") @@ -394,9 +387,9 @@ class TestGlances(unittest.TestCase): assert len(stats_grab) == 0 else: print(stats_grab) - self.assertTrue(stat in stats_grab[0].keys(), msg='Cannot find key: %s' % stat) + self.assertTrue(stat in stats_grab[0].keys(), msg=f'Cannot find key: {stat}') - print('INFO: SMART stats: %s' % stats_grab) + print(f'INFO: SMART stats: {stats_grab}') def test_017_programs(self): """Check Programs function (it's not a plugin).""" @@ -515,9 +508,7 @@ class TestGlances(unittest.TestCase): plugins_list = stats.getPluginsList() for plugin in plugins_list: for method in mandatories_methods: - self.assertTrue( - hasattr(stats.get_plugin(plugin), method), msg='{} has no method {}()'.format(plugin, method) - ) + self.assertTrue(hasattr(stats.get_plugin(plugin), method), msg=f'{plugin} has no method {method}()') def test_096_views(self): """Test get_views method""" @@ -526,7 +517,7 @@ class TestGlances(unittest.TestCase): for plugin in plugins_list: stats.get_plugin(plugin).get_raw() views_grab = stats.get_plugin(plugin).get_views() - self.assertTrue(isinstance(views_grab, dict), msg='{} view is not a dict'.format(plugin)) + self.assertTrue(isinstance(views_grab, dict), msg=f'{plugin} view is not a dict') def test_097_attribute(self): """Test GlancesAttribute classes""" @@ -675,7 +666,7 @@ class TestGlances(unittest.TestCase): snapshot_end = tracemalloc.take_snapshot() snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') memory_leak = sum([s.size_diff for s in snapshot_diff]) - print('INFO: Memory leak: {} bytes'.format(memory_leak)) + print(f'INFO: Memory leak: {memory_leak} bytes') # snapshot_begin = tracemalloc.take_snapshot() for _ in range(30): @@ -683,7 +674,7 @@ class TestGlances(unittest.TestCase): snapshot_end = tracemalloc.take_snapshot() snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') memory_leak = sum([s.size_diff for s in snapshot_diff]) - print('INFO: Memory leak: {} bytes'.format(memory_leak)) + print(f'INFO: Memory leak: {memory_leak} bytes') # snapshot_begin = tracemalloc.take_snapshot() for _ in range(300): @@ -691,7 +682,7 @@ class TestGlances(unittest.TestCase): snapshot_end = tracemalloc.take_snapshot() snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename') memory_leak = sum([s.size_diff for s in snapshot_diff]) - print('INFO: Memory leak: {} bytes'.format(memory_leak)) + print(f'INFO: Memory leak: {memory_leak} bytes') snapshot_top = snapshot_end.compare_to(snapshot_begin, 'traceback') print("Memory consumption (top 5):") for stat in snapshot_top[:5]: diff --git a/unittest-restful.py b/unittest-restful.py index 72e99b2e..7f0b1eea 100755 --- a/unittest-restful.py +++ b/unittest-restful.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Glances - An eye on your system # @@ -25,12 +24,12 @@ from glances.outputs.glances_restful_api import GlancesRestfulApi SERVER_PORT = 61234 API_VERSION = GlancesRestfulApi.API_VERSION -URL = "http://localhost:{}/api/{}".format(SERVER_PORT, API_VERSION) +URL = f"http://localhost:{SERVER_PORT}/api/{API_VERSION}" pid = None # Unitest class # ============== -print('RESTful API unitary tests for Glances %s' % __version__) +print(f'RESTful API unitary tests for Glances {__version__}') class TestGlances(unittest.TestCase): @@ -57,8 +56,8 @@ class TestGlances(unittest.TestCase): cmdline = "./venv/bin/python" else: cmdline = "python" - cmdline += " -m glances -B 0.0.0.0 -w -p %s --disable-webui -C ./conf/glances.conf" % SERVER_PORT - print("Run the Glances Web Server on port %s" % SERVER_PORT) + cmdline += f" -m glances -B 0.0.0.0 -w -p {SERVER_PORT} --disable-webui -C ./conf/glances.conf" + print(f"Run the Glances Web Server on port {SERVER_PORT}") args = shlex.split(cmdline) pid = subprocess.Popen(args) print("Please wait 5 seconds...") @@ -70,8 +69,8 @@ class TestGlances(unittest.TestCase): """All.""" method = "all" print('INFO: [TEST_001] Get all stats') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertTrue(req.json(), dict) @@ -80,8 +79,8 @@ class TestGlances(unittest.TestCase): """Plugins list.""" method = "pluginslist" print('INFO: [TEST_002] Plugins list') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), list) @@ -91,11 +90,11 @@ class TestGlances(unittest.TestCase): """Plugins.""" method = "pluginslist" print('INFO: [TEST_003] Plugins') - plist = self.http_get("%s/%s" % (URL, method)) + plist = self.http_get(f"{URL}/{method}") for p in plist.json(): - print("HTTP RESTful request: %s/%s" % (URL, p)) - req = self.http_get("%s/%s" % (URL, p)) + print(f"HTTP RESTful request: {URL}/{p}") + req = self.http_get(f"{URL}/{p}") self.assertTrue(req.ok) if p in ('uptime', 'version', 'psutilversion'): self.assertIsInstance(req.json(), text_type) @@ -127,11 +126,11 @@ class TestGlances(unittest.TestCase): """Items.""" method = "cpu" print('INFO: [TEST_004] Items for the CPU method') - ilist = self.http_get("%s/%s" % (URL, method)) + ilist = self.http_get(f"{URL}/{method}") for i in ilist.json(): - print("HTTP RESTful request: %s/%s/%s" % (URL, method, i)) - req = self.http_get("%s/%s/%s" % (URL, method, i)) + print(f"HTTP RESTful request: {URL}/{method}/{i}") + req = self.http_get(f"{URL}/{method}/{i}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) print(req.json()[i]) @@ -141,8 +140,8 @@ class TestGlances(unittest.TestCase): """Values.""" method = "processlist" print('INFO: [TEST_005] Item=Value for the PROCESSLIST method') - print("%s/%s/pid/0" % (URL, method)) - req = self.http_get("%s/%s/pid/0" % (URL, method)) + print(f"{URL}/{method}/pid/0") + req = self.http_get(f"{URL}/{method}/pid/0") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) @@ -151,8 +150,8 @@ class TestGlances(unittest.TestCase): """All limits.""" method = "all/limits" print('INFO: [TEST_006] Get all limits') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) @@ -161,8 +160,8 @@ class TestGlances(unittest.TestCase): """All views.""" method = "all/views" print('INFO: [TEST_007] Get all views') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) @@ -171,11 +170,11 @@ class TestGlances(unittest.TestCase): """Plugins limits.""" method = "pluginslist" print('INFO: [TEST_008] Plugins limits') - plist = self.http_get("%s/%s" % (URL, method)) + plist = self.http_get(f"{URL}/{method}") for p in plist.json(): - print("HTTP RESTful request: %s/%s/limits" % (URL, p)) - req = self.http_get("%s/%s/limits" % (URL, p)) + print(f"HTTP RESTful request: {URL}/{p}/limits") + req = self.http_get(f"{URL}/{p}/limits") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) @@ -183,11 +182,11 @@ class TestGlances(unittest.TestCase): """Plugins views.""" method = "pluginslist" print('INFO: [TEST_009] Plugins views') - plist = self.http_get("%s/%s" % (URL, method)) + plist = self.http_get(f"{URL}/{method}") for p in plist.json(): - print("HTTP RESTful request: %s/%s/views" % (URL, p)) - req = self.http_get("%s/%s/views" % (URL, p)) + print(f"HTTP RESTful request: {URL}/{p}/views") + req = self.http_get(f"{URL}/{p}/views") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) @@ -195,22 +194,22 @@ class TestGlances(unittest.TestCase): """History.""" method = "history" print('INFO: [TEST_010] History') - print("HTTP RESTful request: %s/cpu/%s" % (URL, method)) - req = self.http_get("%s/cpu/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/cpu/{method}") + req = self.http_get(f"{URL}/cpu/{method}") self.assertIsInstance(req.json(), dict) self.assertIsInstance(req.json()['user'], list) self.assertTrue(len(req.json()['user']) > 0) - print("HTTP RESTful request: %s/cpu/%s/3" % (URL, method)) - req = self.http_get("%s/cpu/%s/3" % (URL, method)) + print(f"HTTP RESTful request: {URL}/cpu/{method}/3") + req = self.http_get(f"{URL}/cpu/{method}/3") self.assertIsInstance(req.json(), dict) self.assertIsInstance(req.json()['user'], list) self.assertTrue(len(req.json()['user']) > 1) - print("HTTP RESTful request: %s/cpu/system/%s" % (URL, method)) - req = self.http_get("%s/cpu/system/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/cpu/system/{method}") + req = self.http_get(f"{URL}/cpu/system/{method}") self.assertIsInstance(req.json(), list) self.assertIsInstance(req.json()[0], list) - print("HTTP RESTful request: %s/cpu/system/%s/3" % (URL, method)) - req = self.http_get("%s/cpu/system/%s/3" % (URL, method)) + print(f"HTTP RESTful request: {URL}/cpu/system/{method}/3") + req = self.http_get(f"{URL}/cpu/system/{method}/3") self.assertIsInstance(req.json(), list) self.assertIsInstance(req.json()[0], list) @@ -218,7 +217,7 @@ class TestGlances(unittest.TestCase): """Check issue #1401.""" method = "network/interface_name" print('INFO: [TEST_011] Issue #1401') - req = self.http_get("%s/%s" % (URL, method)) + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) self.assertIsInstance(req.json()['interface_name'], list) @@ -227,8 +226,8 @@ class TestGlances(unittest.TestCase): """Check status endpoint.""" method = "status" print('INFO: [TEST_012] Status') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method)) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertEqual(req.json()['version'], __version__) @@ -236,7 +235,7 @@ class TestGlances(unittest.TestCase): def test_013_top(self): """Values.""" method = "processlist" - request = "%s/%s/top/2" % (URL, method) + request = f"{URL}/{method}/top/2" print('INFO: [TEST_013] Top nb item of PROCESSLIST') print(request) req = self.http_get(request) @@ -250,11 +249,11 @@ class TestGlances(unittest.TestCase): method = "config" print('INFO: [TEST_014] Get config') - req = self.http_get("%s/%s" % (URL, method)) + req = self.http_get(f"{URL}/{method}") self.assertTrue(req.ok) self.assertIsInstance(req.json(), dict) - req = self.http_get("%s/%s/global/refresh" % (URL, method)) + req = self.http_get(f"{URL}/{method}/global/refresh") self.assertTrue(req.ok) self.assertEqual(req.json(), "2") @@ -262,8 +261,8 @@ class TestGlances(unittest.TestCase): """All with Gzip.""" method = "all" print('INFO: [TEST_015] Get all stats (with GZip compression)') - print("HTTP RESTful request: %s/%s" % (URL, method)) - req = self.http_get("%s/%s" % (URL, method), gzip=True) + print(f"HTTP RESTful request: {URL}/{method}") + req = self.http_get(f"{URL}/{method}", gzip=True) self.assertTrue(req.ok) self.assertTrue(req.headers['Content-Encoding'] == 'gzip') @@ -273,13 +272,13 @@ class TestGlances(unittest.TestCase): """Fields description.""" print('INFO: [TEST_016] Get fields description and unit') - print("HTTP RESTful request: %s/cpu/total/description" % URL) - req = self.http_get("%s/cpu/total/description" % URL) + print(f"HTTP RESTful request: {URL}/cpu/total/description") + req = self.http_get(f"{URL}/cpu/total/description") self.assertTrue(req.ok) self.assertTrue(req.json(), str) - print("HTTP RESTful request: %s/cpu/total/unit" % URL) - req = self.http_get("%s/cpu/total/unit" % URL) + print(f"HTTP RESTful request: {URL}/cpu/total/unit") + req = self.http_get(f"{URL}/cpu/total/unit") self.assertTrue(req.ok) self.assertTrue(req.json(), str) diff --git a/unittest-xmlrpc.py b/unittest-xmlrpc.py index c8b10fb9..b3f48c76 100755 --- a/unittest-xmlrpc.py +++ b/unittest-xmlrpc.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Glances - An eye on your system # @@ -21,7 +20,7 @@ from glances import __version__ from glances.globals import ServerProxy SERVER_PORT = 61234 -URL = "http://localhost:%s" % SERVER_PORT +URL = f"http://localhost:{SERVER_PORT}" pid = None # Init the XML-RPC client @@ -29,7 +28,7 @@ client = ServerProxy(URL) # Unitest class # ============== -print('XML-RPC API unitary tests for Glances %s' % __version__) +print(f'XML-RPC API unitary tests for Glances {__version__}') class TestGlances(unittest.TestCase): @@ -48,8 +47,8 @@ class TestGlances(unittest.TestCase): cmdline = "./venv/bin/python" else: cmdline = "python" - cmdline += " -m glances -B localhost -s -p %s" % SERVER_PORT - print("Run the Glances Server on port %s" % SERVER_PORT) + cmdline += f" -m glances -B localhost -s -p {SERVER_PORT}" + print(f"Run the Glances Server on port {SERVER_PORT}") args = shlex.split(cmdline) pid = subprocess.Popen(args) print("Please wait...") @@ -61,7 +60,7 @@ class TestGlances(unittest.TestCase): """All.""" method = "getAll()" print('INFO: [TEST_001] Connection test') - print("XML-RPC request: %s" % method) + print(f"XML-RPC request: {method}") req = json.loads(client.getAll()) self.assertIsInstance(req, dict) @@ -70,7 +69,7 @@ class TestGlances(unittest.TestCase): """Plugins list.""" method = "getAllPlugins()" print('INFO: [TEST_002] Get plugins list') - print("XML-RPC request: %s" % method) + print(f"XML-RPC request: {method}") req = json.loads(client.getAllPlugins()) self.assertIsInstance(req, list) @@ -78,7 +77,7 @@ class TestGlances(unittest.TestCase): def test_003_system(self): """System.""" method = "getSystem()" - print('INFO: [TEST_003] Method: %s' % method) + print(f'INFO: [TEST_003] Method: {method}') req = json.loads(client.getSystem()) self.assertIsInstance(req, dict) @@ -86,7 +85,7 @@ class TestGlances(unittest.TestCase): def test_004_cpu(self): """CPU.""" method = "getCpu(), getPerCpu(), getLoad() and getCore()" - print('INFO: [TEST_004] Method: %s' % method) + print(f'INFO: [TEST_004] Method: {method}') req = json.loads(client.getCpu()) self.assertIsInstance(req, dict) @@ -103,7 +102,7 @@ class TestGlances(unittest.TestCase): def test_005_mem(self): """MEM.""" method = "getMem() and getMemSwap()" - print('INFO: [TEST_005] Method: %s' % method) + print(f'INFO: [TEST_005] Method: {method}') req = json.loads(client.getMem()) self.assertIsInstance(req, dict) @@ -114,7 +113,7 @@ class TestGlances(unittest.TestCase): def test_006_net(self): """NETWORK.""" method = "getNetwork()" - print('INFO: [TEST_006] Method: %s' % method) + print(f'INFO: [TEST_006] Method: {method}') req = json.loads(client.getNetwork()) self.assertIsInstance(req, list) @@ -122,7 +121,7 @@ class TestGlances(unittest.TestCase): def test_007_disk(self): """DISK.""" method = "getFs(), getFolders() and getDiskIO()" - print('INFO: [TEST_007] Method: %s' % method) + print(f'INFO: [TEST_007] Method: {method}') req = json.loads(client.getFs()) self.assertIsInstance(req, list) @@ -136,7 +135,7 @@ class TestGlances(unittest.TestCase): def test_008_sensors(self): """SENSORS.""" method = "getSensors()" - print('INFO: [TEST_008] Method: %s' % method) + print(f'INFO: [TEST_008] Method: {method}') req = json.loads(client.getSensors()) self.assertIsInstance(req, list) @@ -144,7 +143,7 @@ class TestGlances(unittest.TestCase): def test_009_process(self): """PROCESS.""" method = "getProcessCount() and getProcessList()" - print('INFO: [TEST_009] Method: %s' % method) + print(f'INFO: [TEST_009] Method: {method}') req = json.loads(client.getProcessCount()) self.assertIsInstance(req, dict) @@ -155,7 +154,7 @@ class TestGlances(unittest.TestCase): def test_010_all_limits(self): """All limits.""" method = "getAllLimits()" - print('INFO: [TEST_010] Method: %s' % method) + print(f'INFO: [TEST_010] Method: {method}') req = json.loads(client.getAllLimits()) self.assertIsInstance(req, dict) @@ -164,7 +163,7 @@ class TestGlances(unittest.TestCase): def test_011_all_views(self): """All views.""" method = "getAllViews()" - print('INFO: [TEST_011] Method: %s' % method) + print(f'INFO: [TEST_011] Method: {method}') req = json.loads(client.getAllViews()) self.assertIsInstance(req, dict) @@ -173,14 +172,14 @@ class TestGlances(unittest.TestCase): def test_012_irq(self): """IRQS""" method = "getIrqs()" - print('INFO: [TEST_012] Method: %s' % method) + print(f'INFO: [TEST_012] Method: {method}') req = json.loads(client.getIrq()) self.assertIsInstance(req, list) def test_013_plugin_views(self): """Plugin views.""" method = "getViewsCpu()" - print('INFO: [TEST_013] Method: %s' % method) + print(f'INFO: [TEST_013] Method: {method}') req = json.loads(client.getViewsCpu()) self.assertIsInstance(req, dict) From 28e7e5b74a4b952e500a6bacec234f235a048c89 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 03:28:11 +0530 Subject: [PATCH 08/14] chg: ruff - flake8-comprehensions --- glances/exports/glances_mqtt/__init__.py | 4 ++-- glances/plugins/containers/__init__.py | 2 +- glances/plugins/containers/engines/docker.py | 2 +- glances/plugins/containers/engines/podman.py | 2 +- glances/plugins/diskio/__init__.py | 2 +- glances/plugins/fs/__init__.py | 2 +- glances/plugins/gpu/cards/amd.py | 2 +- glances/plugins/gpu/cards/nvidia.py | 2 +- glances/plugins/network/__init__.py | 2 +- glances/plugins/plugin/model.py | 20 +++++++++----------- glances/plugins/quicklook/__init__.py | 2 +- glances/stats.py | 6 +++--- pyproject.toml | 2 +- unittest-core.py | 6 ++---- 14 files changed, 26 insertions(+), 30 deletions(-) diff --git a/glances/exports/glances_mqtt/__init__.py b/glances/exports/glances_mqtt/__init__.py index 7aeccb03..6c3eaec2 100755 --- a/glances/exports/glances_mqtt/__init__.py +++ b/glances/exports/glances_mqtt/__init__.py @@ -115,7 +115,7 @@ class Export(GlancesExport): sensor_values = dict(zip(columns, points)) # Build the value to output - output_value = dict() + output_value = {} for key in sensor_values: split_key = key.split('.') @@ -123,7 +123,7 @@ class Export(GlancesExport): current_level = output_value for depth in range(len(split_key) - 1): if split_key[depth] not in current_level: - current_level[split_key[depth]] = dict() + current_level[split_key[depth]] = {} current_level = current_level[split_key[depth]] # Add the value diff --git a/glances/plugins/containers/__init__.py b/glances/plugins/containers/__init__.py index bea37ad4..08004e52 100644 --- a/glances/plugins/containers/__init__.py +++ b/glances/plugins/containers/__init__.py @@ -299,7 +299,7 @@ class PluginModel(GlancesPluginModel): show_pod_name = True self.views['show_pod_name'] = show_pod_name show_engine_name = False - if len(set(ct["engine"] for ct in self.stats)) > 1: + if len({ct["engine"] for ct in self.stats}) > 1: show_engine_name = True self.views['show_engine_name'] = show_engine_name diff --git a/glances/plugins/containers/engines/docker.py b/glances/plugins/containers/engines/docker.py index a72c6bcb..066e83a8 100644 --- a/glances/plugins/containers/engines/docker.py +++ b/glances/plugins/containers/engines/docker.py @@ -267,7 +267,7 @@ class DockerContainersExtension: self.stats_fetchers[container.id] = DockerStatsFetcher(container) # Stop threads for non-existing containers - absent_containers = set(iterkeys(self.stats_fetchers)) - set(c.id for c in containers) + absent_containers = set(iterkeys(self.stats_fetchers)) - {c.id for c in containers} for container_id in absent_containers: # Stop the StatsFetcher logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}") diff --git a/glances/plugins/containers/engines/podman.py b/glances/plugins/containers/engines/podman.py index a73f400b..7324ccd6 100644 --- a/glances/plugins/containers/engines/podman.py +++ b/glances/plugins/containers/engines/podman.py @@ -278,7 +278,7 @@ class PodmanContainersExtension: self.container_stats_fetchers[container.id] = PodmanContainerStatsFetcher(container) # Stop threads for non-existing containers - absent_containers = set(iterkeys(self.container_stats_fetchers)) - set(c.id for c in containers) + absent_containers = set(iterkeys(self.container_stats_fetchers)) - {c.id for c in containers} for container_id in absent_containers: # Stop the StatsFetcher logger.debug(f"{self.ext_name} plugin - Stop thread for old container {container_id[:12]}") diff --git a/glances/plugins/diskio/__init__.py b/glances/plugins/diskio/__init__.py index 4c98c6af..05ec9be7 100644 --- a/glances/plugins/diskio/__init__.py +++ b/glances/plugins/diskio/__init__.py @@ -188,7 +188,7 @@ class PluginModel(GlancesPluginModel): # Disk list (sorted by name) for i in self.sorted_stats(): # Hide stats if never be different from 0 (issue #1787) - if all([self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields]): + if all(self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields): continue # Is there an alias for the disk name ? disk_name = i['alias'] if 'alias' in i else i['disk_name'] diff --git a/glances/plugins/fs/__init__.py b/glances/plugins/fs/__init__.py index 74df193c..6b084e6e 100644 --- a/glances/plugins/fs/__init__.py +++ b/glances/plugins/fs/__init__.py @@ -139,7 +139,7 @@ class PluginModel(GlancesPluginModel): logger.debug("Plugin - fs: PsUtil extended fetch failed") else: # Discard duplicates (#2299) and add entries matching allowed fs types - tracked_mnt_points = set(f.mountpoint for f in fs_stat) + tracked_mnt_points = {f.mountpoint for f in fs_stat} for f in all_mounted_fs: if ( any(f.fstype.find(fs_type) >= 0 for fs_type in allowed_fs_types) diff --git a/glances/plugins/gpu/cards/amd.py b/glances/plugins/gpu/cards/amd.py index eb4ead3a..b3a84e04 100644 --- a/glances/plugins/gpu/cards/amd.py +++ b/glances/plugins/gpu/cards/amd.py @@ -64,7 +64,7 @@ class AmdGPU: stats = [] for index, device in enumerate(self.device_folders): - device_stats = dict() + device_stats = {} # Dictionary key is the GPU_ID device_stats['key'] = 'gpu_id' # GPU id (for multiple GPU, start at 0) diff --git a/glances/plugins/gpu/cards/nvidia.py b/glances/plugins/gpu/cards/nvidia.py index 2c9fe54a..dd6216de 100644 --- a/glances/plugins/gpu/cards/nvidia.py +++ b/glances/plugins/gpu/cards/nvidia.py @@ -49,7 +49,7 @@ class NvidiaGPU: stats = [] for index, device_handle in enumerate(self.device_handles): - device_stats = dict() + device_stats = {} # Dictionary key is the GPU_ID device_stats['key'] = 'gpu_id' # GPU id (for multiple GPU, start at 0) diff --git a/glances/plugins/network/__init__.py b/glances/plugins/network/__init__.py index da582db6..396a1d4f 100644 --- a/glances/plugins/network/__init__.py +++ b/glances/plugins/network/__init__.py @@ -259,7 +259,7 @@ class PluginModel(GlancesPluginModel): if ('is_up' in i) and (i['is_up'] is False): continue # Hide stats if never be different from 0 (issue #1787) - if all([self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields]): + if all(self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields): continue # Format stats # Is there an alias for the interface name ? diff --git a/glances/plugins/plugin/model.py b/glances/plugins/plugin/model.py index 502122ca..e7a2dc96 100644 --- a/glances/plugins/plugin/model.py +++ b/glances/plugins/plugin/model.py @@ -93,7 +93,7 @@ class GlancesPluginModel: self.stats_history = self.init_stats_history() # Init the limits (configuration keys) dictionary - self._limits = dict() + self._limits = {} if config is not None: logger.debug(f'Load section {self.plugin_name} in {config.config_file_paths()}') self.load_limits(config=config) @@ -105,7 +105,7 @@ class GlancesPluginModel: self.actions = GlancesActions(args=args) # Init the views - self.views = dict() + self.views = {} # Hide stats if all the hide_zero_fields has never been != 0 # Default is False, always display stats @@ -284,10 +284,8 @@ class GlancesPluginModel: return sorted( self.stats, key=lambda stat: tuple( - map( - lambda part: int(part) if part.isdigit() else part.lower(), - re.split(r"(\d+|\D+)", self.has_alias(stat[key]) or stat[key]), - ) + int(part) if part.isdigit() else part.lower() + for part in re.split(r"(\d+|\D+)", self.has_alias(stat[key]) or stat[key]) ), ) except TypeError: @@ -295,7 +293,7 @@ class GlancesPluginModel: return sorted( self.stats, key=lambda stat: tuple( - map(lambda part: part.lower(), re.split(r"(\d+|\D+)", self.has_alias(stat[key]) or stat[key])) + part.lower() for part in re.split(r"(\d+|\D+)", self.has_alias(stat[key]) or stat[key]) ), ) @@ -453,7 +451,7 @@ class GlancesPluginModel: if isinstance(self.get_raw(), list) and self.get_raw() is not None and self.get_key() is not None: # Stats are stored in a list of dict (ex: NETWORK, FS...) for i in self.get_raw(): - if any([i[f] for f in self.hide_zero_fields]): + if any(i[f] for f in self.hide_zero_fields): for f in self.hide_zero_fields: self.views[i[self.get_key()]][f]['_zero'] = self.views[i[self.get_key()]][f]['hidden'] for f in self.hide_zero_fields: @@ -465,7 +463,7 @@ class GlancesPluginModel: # # Stats are stored in a dict (ex: CPU, LOAD...) for key in listkeys(self.get_raw()): - if any([self.get_raw()[f] for f in self.hide_zero_fields]): + if any(self.get_raw()[f] for f in self.hide_zero_fields): for f in self.hide_zero_fields: self.views[f]['_zero'] = self.views[f]['hidden'] for f in self.hide_zero_fields: @@ -530,7 +528,7 @@ class GlancesPluginModel: def reset_views(self): """Reset the views to input_views.""" - self.views = dict() + self.views = {} def get_views(self, item=None, key=None, option=None): """Return the views object. @@ -888,7 +886,7 @@ class GlancesPluginModel: def read_alias(self): if self.plugin_name + '_' + 'alias' in self._limits: return {i.split(':')[0].lower(): i.split(':')[1] for i in self._limits[self.plugin_name + '_' + 'alias']} - return dict() + return {} def has_alias(self, header): """Return the alias name for the relative header it it exists otherwise None.""" diff --git a/glances/plugins/quicklook/__init__.py b/glances/plugins/quicklook/__init__.py index 0c45d9a3..161e6880 100644 --- a/glances/plugins/quicklook/__init__.py +++ b/glances/plugins/quicklook/__init__.py @@ -179,7 +179,7 @@ class PluginModel(GlancesPluginModel): return ret # Define the data: Bar (default behavior) or Sparkline - data = dict() + data = {} for key in self.stats_list: if self.args.sparkline and self.history_enable() and not self.args.client: data[key] = Sparkline(max_width) diff --git a/glances/stats.py b/glances/stats.py index 99eae439..97b9729e 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -233,7 +233,7 @@ class GlancesStats: """ if enable: return [p for p in self._plugins if self._plugins[p].is_enabled()] - return [p for p in self._plugins] + return list(self._plugins) def getExportsList(self, enable=True): """Return the exports list. @@ -244,8 +244,8 @@ class GlancesStats: :return: list of export module names """ if enable: - return [e for e in self._exports] - return [e for e in self._exports_all] + return list(self._exports) + return list(self._exports_all) def load_limits(self, config=None): """Load the stats limits (except the one in the exclude list).""" diff --git a/pyproject.toml b/pyproject.toml index 7a1f3608..685b228f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ select = [ # "N", # pep8-naming "W", # pycodestyle "UP", # pyupgrde -# "C4", # flake8-comprehensions + "C4", # flake8-comprehensions "RET", # flake8-return # "FBT", # flake8-boolean-trap # "RUF", # Ruff-specific rules diff --git a/unittest-core.py b/unittest-core.py index 6626d6a4..bad2dcf9 100755 --- a/unittest-core.py +++ b/unittest-core.py @@ -74,10 +74,8 @@ class TestGlances(unittest.TestCase): self.assertEqual(plugin_instance.get_key(), None) self.assertTrue( all( - [ - f in [h['name'] for h in plugin_instance.items_history_list] - for f in plugin_instance.get_raw_history() - ] + f in [h['name'] for h in plugin_instance.items_history_list] + for f in plugin_instance.get_raw_history() ) ) elif plugin_instance.history_enable() and isinstance(plugin_instance.get_raw(), list): From cd69c4a0e8965ee0d07183fce29cd58632686cd0 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 03:58:43 +0530 Subject: [PATCH 09/14] chg: ruff - naming exclude already ignores rules with flake8 --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 685b228f..37c78c2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ select = [ "E", # pycodestyle "F", # Pyflakes "I", # isort -# "N", # pep8-naming + "N", # pep8-naming "W", # pycodestyle "UP", # pyupgrde "C4", # flake8-comprehensions @@ -26,7 +26,7 @@ select = [ # "RUF", # Ruff-specific rules # "PERF", # Perflint ] -ignore = [] +ignore = ["N801", "N802", "N803", "N805", "N806", "N807", "N811", "N812", "N813", "N814", "N815", "N816", "N817", "N818"] # Allow autofix for all enabled rules (when `--fix`) is provided. fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"] From 00c662f8704ab21424feb4e1e8620b7d8e840fd4 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 04:13:26 +0530 Subject: [PATCH 10/14] chg: Makefile - use ruff & pre-commit --- Makefile | 12 ++++-------- dev-requirements.txt | 5 +---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index dcf0672d..b7e1e817 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ venv-dev-python: ## Install Python 3 venv venv-dev: venv-python ## Install Python 3 dev dependencies ./venv-dev/bin/pip install -r dev-requirements.txt ./venv-dev/bin/pip install -r doc-requirements.txt + ./venv-dev/bin/pre-commit install --hook-type pre-commit venv-dev-upgrade: ## Upgrade Python 3 dev dependencies ./venv-dev/bin/pip install --upgrade pip @@ -86,15 +87,10 @@ test-min-with-upgrade: venv-min-upgrade ## Upgrade deps and run unit tests in mi # =================================================================== format: ## Format the code - @git ls-files 'glances/*.py' | xargs ./venv-dev/bin/python -m autopep8 --in-place --jobs 0 --global-config=.flake8 - @git ls-files 'glances/*.py' | xargs ./venv-dev/bin/python -m autoflake --in-place --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys --exclude="compat.py,globals.py" - ./venv-dev/bin/python -m black ./glances --exclude outputs/static + ./venv-dev/bin/python -m ruff format . -flake8: ## Run flake8 linter. - @git ls-files 'glances/ *.py' | xargs ./venv-dev/bin/python -m flake8 --config=.flake8 - -ruff: ## Run Ruff (fastest) linter. - ./venv-dev/bin/python -m ruff check . --config=./pyproject.toml +lint: ## Lint the code. + ./venv-dev/bin/python -m ruff check . --fix codespell: ## Run codespell to fix common misspellings in text files ./venv-dev/bin/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics diff --git a/dev-requirements.txt b/dev-requirements.txt index 66534b2f..b0ade583 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,14 +1,11 @@ -autoflake -autopep8 -black codespell -flake8 fonttools>=4.43.0 # not directly required, pinned by Snyk to avoid a vulnerability gprof2dot matplotlib memory-profiler numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability pillow>=10.0.1 # not directly required, pinned by Snyk to avoid a vulnerability +pre-commit py-spy pyright requirements-parser From 14efbac82d63572d0666353ca503e0fb6e645672 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 04:17:33 +0530 Subject: [PATCH 11/14] chore: remove older lint configs --- .bandit | 2 - .flake8 | 8 -- pylint.cfg | 259 ------------------------------------------------- pyproject.toml | 4 + 4 files changed, 4 insertions(+), 269 deletions(-) delete mode 100644 .bandit delete mode 100644 .flake8 delete mode 100644 pylint.cfg diff --git a/.bandit b/.bandit deleted file mode 100644 index eb7ce63c..00000000 --- a/.bandit +++ /dev/null @@ -1,2 +0,0 @@ -[bandit] -exclude: ./docs,./glances/outputs/static/node_modules diff --git a/.flake8 b/.flake8 deleted file mode 100644 index d66d7164..00000000 --- a/.flake8 +++ /dev/null @@ -1,8 +0,0 @@ -[flake8] -exclude = .git,__pycache__,docs/,build,dist -ignore = - W504, B007, B014, B008, B902, Q000, - N801, N802, N803, N806, N807, N811, N812, N813, N814, N815, N816, N817, N818 - -# lines should not exceed 120 characters -max-line-length = 120 diff --git a/pylint.cfg b/pylint.cfg deleted file mode 100644 index 3fd39b7b..00000000 --- a/pylint.cfg +++ /dev/null @@ -1,259 +0,0 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). -disable=C,no-name-in-module - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Include message's id in output -include-ids=no - -# Include symbolic ids of messages in output -symbols=no - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (RP0004). -comment=no - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the beginning of the name of dummy variables -# (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins=_ - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff --git a/pyproject.toml b/pyproject.toml index 37c78c2f..2380aff3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,9 @@ quote-style = "preserve" [tool.ruff.lint] # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. select = [ +# "A", +# "B", +# "S", "C90", # mccabe "E", # pycodestyle "F", # Pyflakes @@ -22,6 +25,7 @@ select = [ "UP", # pyupgrde "C4", # flake8-comprehensions "RET", # flake8-return +# "PL", # "FBT", # flake8-boolean-trap # "RUF", # Ruff-specific rules # "PERF", # Perflint From f31b767e0ec96289ce3fdbc8df97a2bdae0d92d0 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Fri, 17 May 2024 04:41:31 +0530 Subject: [PATCH 12/14] chg: github-actions to use ruff --- .github/workflows/test.yml | 91 +++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 96f70589..efd24232 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,8 +7,32 @@ on: jobs: + source-code-checks: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + + - name: Check formatting with Ruff + uses: chartboost/ruff-action@v1 + with: + args: 'format --check' + + - name: Check linting with Ruff + uses: chartboost/ruff-action@v1 + with: + args: 'check' + + - name: Static type check + run: | + echo "Skipping static type check for the moment, too much error..."; + # pip install pyright + # pyright glances + + test-linux: + needs: source-code-checks # https://github.com/actions/runner-images?tab=readme-ov-file#available-images runs-on: ubuntu-22.04 strategy: @@ -17,36 +41,22 @@ jobs: steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with flake8 - run: | - # Stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=.git,./docs,./glances/outputs/static - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=.git,./docs,./glances/outputs/static - - - name: Static type check - run: | - echo "Skipping static type check for the moment, too much error..."; - # pip install pyright - # pyright glances - - - name: Unitary tests - run: | - python ./unittest-core.py + - name: Unitary tests + run: | + python ./unittest-core.py # Error appear with h11, not related to Glances # Should be tested if correction is done @@ -84,6 +94,7 @@ jobs: test-macos: + needs: source-code-checks # https://github.com/actions/runner-images?tab=readme-ov-file#available-images runs-on: macos-14 strategy: @@ -92,22 +103,22 @@ jobs: steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Unitary tests - run: | - python ./unittest-core.py + - name: Unitary tests + run: | + python ./unittest-core.py # Error when trying to implement #2749 # pkg: No packages available to install matching 'py-pip' have been found in the repositories From 6a0889851cc7df4e555bb72cd39acc14777abe32 Mon Sep 17 00:00:00 2001 From: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com> Date: Sat, 18 May 2024 01:21:32 +0530 Subject: [PATCH 13/14] chg: glances client - avoid logging user creds --- glances/client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glances/client.py b/glances/client.py index 8e598635..a73fedb0 100644 --- a/glances/client.py +++ b/glances/client.py @@ -50,7 +50,9 @@ class GlancesClient: self.uri = f'http://{args.username}:{args.password}@{args.client}:{args.port}' else: self.uri = f'http://{args.client}:{args.port}' - logger.debug(f"Try to connect to {self.uri}") + + # Avoid logging user credentials + logger.debug(f"Try to connect to 'http://{args.client}:{args.port}'") # Try to connect to the URI transport = GlancesClientTransport() From 4f38bf384bfa80a0860abfb5cde6eda8bf3b720c Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sat, 18 May 2024 10:17:47 +0200 Subject: [PATCH 14/14] Add some comment regarding the minimal Python version and exclude all the venv* folders in the linter configuration --- CONTRIBUTING.md | 9 +++------ pyproject.toml | 3 +++ setup.py | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ad1282c4..ddab0ac5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,6 @@ the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features. - ## Using the issue tracker The [issue tracker](https://github.com/nicolargo/glances/issues) is @@ -24,7 +23,6 @@ restrictions: * Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others. - ## Bug reports A bug is a _demonstrable problem_ that is caused by the code in the repository. @@ -65,19 +63,17 @@ Example: > causing the bug, and potential solutions (and your opinions on their > merits). > -> You can also run Glances in debug mode (-d) and paste/bin the glances.conf file (https://glances.readthedocs.io/en/latest/config.html). +> You can also run Glances in debug mode (-d) and paste/bin the glances.conf file (). > > Glances 3.2.0 or higher have also a --issue option to run a simple test. Please use it and copy/paste the output. - ## Feature requests Feature requests are welcome. But take a moment to find out whether your idea -fits with the scope and aims of the project. It's up to *you* to make a strong +fits with the scope and aims of the project. It's up to _you* to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible. - ## Pull requests Good pull requests—patches, improvements, new features—are a fantastic @@ -133,6 +129,7 @@ included in the project: 5. Test you code using the Makefile: + * make format ==> Format your code thanks to the Ruff linter * make run ==> Run Glances * make run-webserver ==> Run a Glances Web Server * make test ==> Run unit tests diff --git a/pyproject.toml b/pyproject.toml index 2380aff3..c5fb7e4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,10 @@ exclude = [ "dist", "node_modules", "venv", + "venv-dev", + "venv-min", "docs", + "test-data", "./glances/outputs/static/*" ] diff --git a/setup.py b/setup.py index d095cb84..d6f6ac6e 100755 --- a/setup.py +++ b/setup.py @@ -8,6 +8,9 @@ import sys from setuptools import Command, setup +# If the minimal Python version is changed then do not forget to change it in: +# - ./pyproject.toml +# - .github/workflows/test.yml if not (sys.version_info >= (3, 8)): print('Glances requires at least Python 3.8 to run.') sys.exit(1)