From b3828f549750405b316a38d4796087ee3a815882 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sat, 16 Dec 2023 15:00:04 +0100 Subject: [PATCH] Replace Bottle by FastAPI #2181 --- Makefile | 2 +- glances/events.py | 6 +- glances/exports/couchdb/__init__.py | 7 +- glances/exports/export.py | 2 +- glances/folder_list.py | 12 +- glances/globals.py | 2 +- glances/main.py | 2 +- glances/outputs/glances_curses.py | 25 +- glances/outputs/glances_restful_api.py | 289 +++++++++++------------ glances/outputs/glances_stdout_apidoc.py | 4 +- glances/plugins/alert/__init__.py | 8 +- glances/plugins/folders/__init__.py | 3 +- glances/plugins/gpu/__init__.py | 7 +- glances/plugins/help/__init__.py | 30 ++- glances/plugins/mem/__init__.py | 5 +- glances/plugins/processlist/__init__.py | 8 +- glances/processes.py | 5 +- glances/programs.py | 6 +- glances/stats.py | 7 +- 19 files changed, 204 insertions(+), 226 deletions(-) diff --git a/Makefile b/Makefile index 1963c931..c8f84a07 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ 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 semgrep: ## Run semgrep to find bugs and enforce code standards - ./venv-dev/bin/semgrep --config=auto --lang python --use-git-ignore ./glances + ./venv-dev/bin/semgrep scan --config=auto profiling: ## How to start the profiling of the Glances software @echo "Please complete and run: sudo ./venv-dev/bin/py-spy record -o ./docs/_static/glances-flame.svg -d 60 -s --pid " diff --git a/glances/events.py b/glances/events.py index 956364f3..2dbc5100 100644 --- a/glances/events.py +++ b/glances/events.py @@ -13,7 +13,6 @@ import time from datetime import datetime from glances.processes import glances_processes, sort_stats -from glances.logger import logger class GlancesEvents(object): @@ -109,8 +108,7 @@ class GlancesEvents(object): self._create_event(event_state, event_type, event_value, proc_desc) else: # Event exist, update it - self._update_event(event_index, - event_state, event_type, event_value, proc_list, proc_desc, peak_time) + self._update_event(event_index, event_state, event_type, event_value, proc_list, proc_desc, peak_time) return self.len() @@ -130,7 +128,7 @@ class GlancesEvents(object): time.mktime(datetime.now().timetuple()), # START DATE -1, # END DATE event_state, # STATE: WARNING|CRITICAL - event_type, # TYPE: CPU, LOAD, MEM... + event_type, # TYPE: CPU, LOAD, MEM... event_value, # MAX event_value, # AVG event_value, # MIN diff --git a/glances/exports/couchdb/__init__.py b/glances/exports/couchdb/__init__.py index 7f3a216a..5cc65529 100644 --- a/glances/exports/couchdb/__init__.py +++ b/glances/exports/couchdb/__init__.py @@ -36,9 +36,7 @@ class Export(GlancesExport): # Load the CouchDB configuration file section # User and Password are mandatory with CouchDB 3.0 and higher - self.export_enable = self.load_conf('couchdb', - mandatories=['host', 'port', 'db', - 'user', 'password']) + self.export_enable = self.load_conf('couchdb', mandatories=['host', 'port', 'db', 'user', 'password']) if not self.export_enable: sys.exit(2) @@ -51,8 +49,7 @@ class Export(GlancesExport): return None # @TODO: https - server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, - self.host, self.port) + server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port) try: s = pycouchdb.Server(server_uri) diff --git a/glances/exports/export.py b/glances/exports/export.py index 914db71c..45a08c77 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -36,7 +36,7 @@ class GlancesExport(object): 'processlist', 'psutilversion', 'quicklook', - 'version' + 'version', ] def __init__(self, config=None, args=None): diff --git a/glances/folder_list.py b/glances/folder_list.py index 2dccab93..595c536f 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -10,7 +10,6 @@ """Manage the folder list.""" from __future__ import unicode_literals -import os from glances.timer import Timer from glances.globals import nativestr, folder_size @@ -132,11 +131,12 @@ class FolderList(object): # Get folder size self.__folder_list[i]['size'], self.__folder_list[i]['errno'] = folder_size(self.path(i)) if self.__folder_list[i]['errno'] != 0: - logger.debug('Folder size ({} ~ {}) may not be correct. Error: {}'.format( - self.path(i), - self.__folder_list[i]['size'], - self.__folder_list[i]['errno'])) - # Reset the timer + logger.debug( + 'Folder size ({} ~ {}) may not be correct. Error: {}'.format( + self.path(i), self.__folder_list[i]['size'], self.__folder_list[i]['errno'] + ) + ) + # Reset the timer self.timer_folders[i].reset() # It is no more the first time... diff --git a/glances/globals.py b/glances/globals.py index 46f47f7b..315d0d57 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -413,8 +413,8 @@ def folder_size(path, errno=0): def weak_lru_cache(maxsize=128, typed=False): """LRU Cache decorator that keeps a weak reference to self Source: https://stackoverflow.com/a/55990799""" - def wrapper(func): + def wrapper(func): @functools.lru_cache(maxsize, typed) def _func(_self, *args, **kwargs): return func(_self(), *args, **kwargs) diff --git a/glances/main.py b/glances/main.py index 6a449aa5..5fe92471 100644 --- a/glances/main.py +++ b/glances/main.py @@ -134,7 +134,7 @@ Examples of use: '--enable-plugins', '--enable', dest='enable_plugin', - help='enable plugin (comma-separated list)' + help='enable plugin (comma-separated list)', ) parser.add_argument( '--disable-process', diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index f5ba10ad..f4e70c81 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -101,15 +101,7 @@ class _GlancesCurses(object): _sort_loop = sort_processes_key_list # Define top menu - _top = [ - 'quicklook', - 'cpu', - 'percpu', - 'gpu', - 'mem', - 'memswap', - 'load' - ] + _top = ['quicklook', 'cpu', 'percpu', 'gpu', 'mem', 'memswap', 'load'] _quicklook_max_width = 68 # Define left sidebar @@ -131,13 +123,7 @@ class _GlancesCurses(object): _left_sidebar_max_width = 34 # Define right sidebar - _right_sidebar = [ - 'containers', - 'processcount', - 'amps', - 'processlist', - 'alert' - ] + _right_sidebar = ['containers', 'processcount', 'amps', 'processlist', 'alert'] def __init__(self, config=None, args=None): # Init @@ -301,8 +287,7 @@ class _GlancesCurses(object): if curses.COLORS > 8: # ex: export TERM=xterm-256color - colors_list = [curses.COLOR_CYAN, - curses.COLOR_YELLOW] + colors_list = [curses.COLOR_CYAN, curses.COLOR_YELLOW] for i in range(0, 3): try: curses.init_pair(i + 9, colors_list[i], -1) @@ -462,9 +447,7 @@ class _GlancesCurses(object): ) def _handle_sort_key(self, hotkey): - glances_processes.set_sort_key( - self._hotkeys[hotkey]['sort_key'], self._hotkeys[hotkey]['sort_key'] == 'auto' - ) + glances_processes.set_sort_key(self._hotkeys[hotkey]['sort_key'], self._hotkeys[hotkey]['sort_key'] == 'auto') def _handle_enter(self): self.edit_filter = not self.edit_filter diff --git a/glances/outputs/glances_restful_api.py b/glances/outputs/glances_restful_api.py index 02a86cf8..f4dfde6d 100644 --- a/glances/outputs/glances_restful_api.py +++ b/glances/outputs/glances_restful_api.py @@ -16,6 +16,7 @@ from io import open import webbrowser import socket from urllib.parse import urljoin + # Replace typing_extensions by typing when Python 3.8 support will be dropped # from typing import Annotated from typing_extensions import Annotated @@ -72,15 +73,12 @@ 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('http://{}:{}/'.format(self.args.bind_address, self.args.port), self.url_prefix) # FastAPI Init if self.args.password: self._app = FastAPI(dependencies=[Depends(self.authentication)]) - self._password = GlancesPassword(username=args.username, - config=config) + self._password = GlancesPassword(username=args.username, config=config) else: self._app = FastAPI() @@ -100,9 +98,7 @@ class GlancesRestfulApi(object): self._app.add_middleware( CORSMiddleware, # allow_origins=["*"], - allow_origins=[ - self.bind_url - ], + allow_origins=[self.bind_url], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], @@ -110,8 +106,7 @@ class GlancesRestfulApi(object): # FastAPI Enable GZIP compression # https://fastapi.tiangolo.com/advanced/middleware/ - self._app.add_middleware(GZipMiddleware, - minimum_size=1000) + self._app.add_middleware(GZipMiddleware, minimum_size=1000) # FastAPI Define routes self._app.include_router(self._router()) @@ -139,8 +134,7 @@ class GlancesRestfulApi(object): """Check if a username/password combination is valid.""" if creds.username == self.args.username: # check_password and get_hash are (lru) cached to optimize the requests - if self._password.check_password(self.args.password, - self._password.get_hash(creds.password)): + if self._password.check_password(self.args.password, self._password.get_hash(creds.password)): return creds.username # If the username/password combination is invalid, return an HTTP 401 @@ -155,74 +149,80 @@ class GlancesRestfulApi(object): router = APIRouter() # REST API - router.add_api_route('/api/%s/status' % self.API_VERSION, - status_code=status.HTTP_200_OK, - response_class=ORJSONResponse, - endpoint=self._api_status) + router.add_api_route( + '/api/%s/status' % self.API_VERSION, + 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) - router.add_api_route('/api/%s/config/{section}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_config_section) - router.add_api_route('/api/%s/config/{section}/{item}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_config_section_item) + router.add_api_route( + '/api/%s/config' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_config + ) + router.add_api_route( + '/api/%s/config/{section}' % self.API_VERSION, + response_class=ORJSONResponse, + endpoint=self._api_config_section, + ) + router.add_api_route( + '/api/%s/config/{section}/{item}' % self.API_VERSION, + 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('/api/%s/args/{item}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_args_item) + router.add_api_route('/api/%s/args' % self.API_VERSION, 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 + ) - router.add_api_route('/api/%s/pluginslist' % self.API_VERSION, - 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('/api/%s/all/limits' % self.API_VERSION, - 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) + router.add_api_route( + '/api/%s/pluginslist' % self.API_VERSION, 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( + '/api/%s/all/limits' % self.API_VERSION, 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 + ) - 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('/api/%s/{plugin}/history' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_history) - router.add_api_route('/api/%s/{plugin}/history/{nb}' % self.API_VERSION, - 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) - router.add_api_route('/api/%s/{plugin}/limits' % self.API_VERSION, - 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) - router.add_api_route('/api/%s/{plugin}/{item}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_item) - router.add_api_route('/api/%s/{plugin}/{item}/history' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_item_history) - router.add_api_route('/api/%s/{plugin}/{item}/history/{nb}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_item_history) - router.add_api_route('/api/%s/{plugin}/{item}/{value}' % self.API_VERSION, - response_class=ORJSONResponse, - endpoint=self._api_value) + 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( + '/api/%s/{plugin}/history' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_history + ) + router.add_api_route( + '/api/%s/{plugin}/history/{nb}' % self.API_VERSION, + 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 + ) + router.add_api_route( + '/api/%s/{plugin}/limits' % self.API_VERSION, 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 + ) + router.add_api_route( + '/api/%s/{plugin}/{item}' % self.API_VERSION, response_class=ORJSONResponse, endpoint=self._api_item + ) + router.add_api_route( + '/api/%s/{plugin}/{item}/history' % self.API_VERSION, + response_class=ORJSONResponse, + endpoint=self._api_item_history, + ) + router.add_api_route( + '/api/%s/{plugin}/{item}/history/{nb}' % self.API_VERSION, + response_class=ORJSONResponse, + endpoint=self._api_item_history, + ) + router.add_api_route( + '/api/%s/{plugin}/{item}/{value}' % self.API_VERSION, + response_class=ORJSONResponse, + endpoint=self._api_value, + ) # Restful API bindmsg = 'Glances RESTful API Server started on {}api/{}'.format(self.bind_url, self.API_VERSION) @@ -231,14 +231,10 @@ class GlancesRestfulApi(object): # WEB UI if not self.args.disable_webui: # Template for the root index.html file - router.add_api_route('/', - response_class=HTMLResponse, - endpoint=self._index) + router.add_api_route('/', response_class=HTMLResponse, endpoint=self._index) # Statics files - self._app.mount("/static", - StaticFiles(directory=self.STATIC_PATH), - name="static") + self._app.mount("/static", StaticFiles(directory=self.STATIC_PATH), name="static") bindmsg = 'Glances Web User Interface started on {}'.format(self.bind_url) else: @@ -267,10 +263,7 @@ class GlancesRestfulApi(object): # Run the Web application try: - uvicorn.run(self._app, - host=self.args.bind_address, - port=self.args.port, - access_log=self.args.debug) + uvicorn.run(self._app, host=self.args.bind_address, port=self.args.port, access_log=self.args.debug) except socket.error as e: logger.critical('Error: Can not ran Glances Web server ({})'.format(e)) @@ -286,18 +279,19 @@ class GlancesRestfulApi(object): Note: This function is only called the first time the page is loaded. """ - refresh_time = request.query_params.get('refresh', - default=max(1, int(self.args.time))) + refresh_time = request.query_params.get('refresh', default=max(1, int(self.args.time))) # Update the stat self.__update__() # Display - return self._templates.TemplateResponse("index.html", - { - "request": request, - "refresh_time": refresh_time, - }) + return self._templates.TemplateResponse( + "index.html", + { + "request": request, + "refresh_time": refresh_time, + }, + ) def _api_status(self): """Glances API RESTful implementation. @@ -318,9 +312,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="Cannot get help view data (%s)" % str(e)) return ORJSONResponse(plist) @@ -356,9 +348,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="Cannot get plugin list (%s)" % str(e)) return ORJSONResponse(plist) @@ -385,9 +375,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="Cannot get stats (%s)" % str(e)) return ORJSONResponse(statval) @@ -403,9 +391,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="Cannot get limits (%s)" % str(e)) return ORJSONResponse(limits) @@ -421,9 +407,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="Cannot get views (%s)" % str(e)) return ORJSONResponse(limits) @@ -438,7 +422,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -448,8 +433,8 @@ class GlancesRestfulApi(object): 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))) + status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e)) + ) return ORJSONResponse(statval) @@ -466,7 +451,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -476,8 +462,8 @@ class GlancesRestfulApi(object): statval = self.stats.get_plugin(plugin).get_export() except Exception as e: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Cannot get plugin %s (%s)" % (plugin, str(e))) + status_code=status.HTTP_404_NOT_FOUND, detail="Cannot get plugin %s (%s)" % (plugin, str(e)) + ) if isinstance(statval, list): statval = statval[:nb] @@ -496,7 +482,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -506,8 +493,8 @@ 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="Cannot get plugin history %s (%s)" % (plugin, str(e)) + ) return statval @@ -522,15 +509,16 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) try: # Get the RAW value of the stat limits 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="Cannot get limits for plugin %s (%s)" % (plugin, str(e)) + ) return ORJSONResponse(ret) @@ -545,15 +533,16 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) try: # Get the RAW value of the stat views 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="Cannot get views for plugin %s (%s)" % (plugin, str(e)) + ) return ORJSONResponse(ret) @@ -568,7 +557,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -579,7 +569,8 @@ 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="Cannot get item %s in plugin %s (%s)" % (item, plugin, str(e)), + ) return ORJSONResponse(ret) @@ -595,7 +586,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -605,8 +597,8 @@ 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="Cannot get history for plugin %s (%s)" % (plugin, str(e)) + ) return ORJSONResponse(ret) @@ -621,7 +613,8 @@ 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="Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list), + ) # Update the stat self.__update__() @@ -632,7 +625,8 @@ 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="Cannot get %s = %s for plugin %s (%s)" % (item, value, plugin, str(e)), + ) return ORJSONResponse(ret) @@ -647,9 +641,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="Cannot get config (%s)" % str(e)) return ORJSONResponse(args_json) @@ -664,16 +656,16 @@ 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) + status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % 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="Cannot get config section %s (%s)" % (section, str(e)) + ) return ORJSONResponse(ret_section) @@ -688,16 +680,16 @@ 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) + status_code=status.HTTP_400_BAD_REQUEST, detail="Unknown configuration item %s" % 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="Cannot get config section %s (%s)" % (section, str(e)) + ) try: # Get the RAW value of the config' dict item @@ -705,7 +697,8 @@ 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="Cannot get item %s in config section %s (%s)" % (item, section, str(e)), + ) return ORJSONResponse(ret_item) @@ -722,9 +715,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="Cannot get args (%s)" % str(e)) return ORJSONResponse(args_json) @@ -737,9 +728,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="Unknown argument item %s" % item) try: # Get the RAW value of the args' dict @@ -747,8 +736,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="Cannot get args item (%s)" % str(e)) return ORJSONResponse(args_json) diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 1eed2fe0..1857be78 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -64,7 +64,9 @@ 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=GlancesRestfulApi.API_VERSION) +""".format( + api_version=GlancesRestfulApi.API_VERSION +) def indent_stat(stat, indent=' '): diff --git a/glances/plugins/alert/__init__.py b/glances/plugins/alert/__init__.py index 42dcb442..0d3908a9 100644 --- a/glances/plugins/alert/__init__.py +++ b/glances/plugins/alert/__init__.py @@ -13,7 +13,6 @@ from datetime import datetime from time import tzname import pytz -from glances.logger import logger from glances.events import glances_events from glances.thresholds import glances_thresholds @@ -173,9 +172,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(PluginModel, self).__init__(args=args, config=config, stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True @@ -213,8 +210,7 @@ class PluginModel(GlancesPluginModel): # New line ret.append(self.curse_new_line()) # Start - msg = str(datetime.fromtimestamp(alert[0], - tz=pytz.timezone(tzname[0] if tzname[0] else 'UTC'))) + msg = str(datetime.fromtimestamp(alert[0], tz=pytz.timezone(tzname[0] if tzname[0] else 'UTC'))) ret.append(self.curse_add_line(msg)) # Duration if alert[1] > 0: diff --git a/glances/plugins/folders/__init__.py b/glances/plugins/folders/__init__.py index 7c5a098e..f4e28db4 100644 --- a/glances/plugins/folders/__init__.py +++ b/glances/plugins/folders/__init__.py @@ -10,7 +10,6 @@ """Folder plugin.""" from __future__ import unicode_literals -import numbers from glances.globals import nativestr from glances.folder_list import FolderList as glancesFolderList @@ -108,7 +107,7 @@ class PluginModel(GlancesPluginModel): ret.append(self.curse_new_line()) if len(i['path']) > name_max_width: # Cut path if it is too long - path = '_' + i['path'][-name_max_width + 1:] + path = '_' + i['path'][-name_max_width + 1 :] else: path = i['path'] msg = '{:{width}}'.format(nativestr(path), width=name_max_width) diff --git a/glances/plugins/gpu/__init__.py b/glances/plugins/gpu/__init__.py index a4a1d924..3d3a73cf 100644 --- a/glances/plugins/gpu/__init__.py +++ b/glances/plugins/gpu/__init__.py @@ -39,10 +39,9 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" - super(PluginModel, self).__init__(args=args, - config=config, - items_history_list=items_history_list, - stats_init_value=[]) + super(PluginModel, self).__init__( + args=args, config=config, items_history_list=items_history_list, stats_init_value=[] + ) # Init the Nvidia API self.init_nvidia() diff --git a/glances/plugins/help/__init__.py b/glances/plugins/help/__init__.py index 5138f00d..fd7a2459 100644 --- a/glances/plugins/help/__init__.py +++ b/glances/plugins/help/__init__.py @@ -184,9 +184,33 @@ class PluginModel(GlancesPluginModel): ret.append(self.curse_new_line()) ret.append(self.curse_add_line('Colors binding:')) ret.append(self.curse_new_line()) - for c in ['DEFAULT', 'UNDERLINE', 'BOLD', 'SORT', 'OK', 'MAX', 'FILTER', 'TITLE', 'PROCESS', 'PROCESS_SELECTED', - 'STATUS', 'NICE', 'CPU_TIME', 'CAREFUL', 'WARNING', 'CRITICAL', 'OK_LOG', 'CAREFUL_LOG', - 'WARNING_LOG', 'CRITICAL_LOG', 'PASSWORD', 'SELECTED', 'INFO', 'ERROR', 'SEPARATOR']: + for c in [ + 'DEFAULT', + 'UNDERLINE', + 'BOLD', + 'SORT', + 'OK', + 'MAX', + 'FILTER', + 'TITLE', + 'PROCESS', + 'PROCESS_SELECTED', + 'STATUS', + 'NICE', + 'CPU_TIME', + 'CAREFUL', + 'WARNING', + 'CRITICAL', + 'OK_LOG', + 'CAREFUL_LOG', + 'WARNING_LOG', + 'CRITICAL_LOG', + 'PASSWORD', + 'SELECTED', + 'INFO', + 'ERROR', + 'SEPARATOR', + ]: ret.append(self.curse_add_line(c, decoration=c)) if c == 'CPU_TIME': ret.append(self.curse_new_line()) diff --git a/glances/plugins/mem/__init__.py b/glances/plugins/mem/__init__.py index fb000b2d..52ceed0c 100644 --- a/glances/plugins/mem/__init__.py +++ b/glances/plugins/mem/__init__.py @@ -115,10 +115,7 @@ class PluginModel(GlancesPluginModel): def __init__(self, args=None, config=None): """Init the plugin.""" super(PluginModel, self).__init__( - args=args, - config=config, - items_history_list=items_history_list, - fields_description=fields_description + args=args, config=config, items_history_list=items_history_list, fields_description=fields_description ) # We want to display the stat in the curse interface diff --git a/glances/plugins/processlist/__init__.py b/glances/plugins/processlist/__init__.py index f3863cfb..6ec05133 100644 --- a/glances/plugins/processlist/__init__.py +++ b/glances/plugins/processlist/__init__.py @@ -583,8 +583,7 @@ class PluginModel(GlancesPluginModel): for k, v in p['memory_info'].items(): ret.append( self.curse_add_line( - self.auto_unit(v, - low_precision=False), + self.auto_unit(v, low_precision=False), decoration='INFO', splittable=True, ) @@ -593,10 +592,7 @@ class PluginModel(GlancesPluginModel): if 'memory_swap' in p and p['memory_swap'] is not None: ret.append( self.curse_add_line( - self.auto_unit(p['memory_swap'], - low_precision=False), - decoration='INFO', - splittable=True + self.auto_unit(p['memory_swap'], low_precision=False), decoration='INFO', splittable=True ) ) ret.append(self.curse_add_line(' swap ', splittable=True)) diff --git a/glances/processes.py b/glances/processes.py index 774d8cf8..5fb43ae0 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -482,8 +482,9 @@ class GlancesProcesses(object): processlist = list(filter(lambda p: not self._filter.is_filtered(p), processlist)) # Save the new processlist and transform all namedtuples to dict - self.processlist = [{k: (v._asdict() if hasattr(v, '_asdict') else v) - for k, v in p.items()} for p in processlist] + self.processlist = [ + {k: (v._asdict() if hasattr(v, '_asdict') else v) for k, v in p.items()} for p in processlist + ] # Compute the maximum value for keys in self._max_values_list: CPU, MEM # Useful to highlight the processes with maximum values diff --git a/glances/programs.py b/glances/programs.py index 55d306aa..d504f386 100644 --- a/glances/programs.py +++ b/glances/programs.py @@ -44,10 +44,8 @@ def update_program_dict(program, p): program['num_threads'] += p['num_threads'] or 0 program['cpu_percent'] += p['cpu_percent'] or 0 program['memory_percent'] += p['memory_percent'] or 0 - program['cpu_times'] = dict(Counter(program['cpu_times'] or {}) + - Counter(p['cpu_times'] or {})) - program['memory_info'] = dict(Counter(program['memory_info'] or {}) + - Counter(p['memory_info'] or {})) + program['cpu_times'] = dict(Counter(program['cpu_times'] or {}) + Counter(p['cpu_times'] or {})) + program['memory_info'] = dict(Counter(program['memory_info'] or {}) + Counter(p['memory_info'] or {})) program['io_counters'] += p['io_counters'] program['childrens'].append(p['pid']) diff --git a/glances/stats.py b/glances/stats.py index 3e0fee40..3929f337 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -138,9 +138,10 @@ class GlancesStats(object): logger.debug("Active plugins list: {}".format(self.getPluginsList())) def load_additional_plugins(self, args=None, config=None): - """ Load additional plugins if defined """ + """Load additional plugins if defined""" + def get_addl_plugins(self, plugin_path): - """ Get list of additonal plugins """ + """Get list of additonal plugins""" _plugin_list = [] for plugin in os.listdir(plugin_path): path = os.path.join(plugin_path, plugin) @@ -175,7 +176,7 @@ class GlancesStats(object): else: start_duration.reset() try: - _mod_loaded = import_module(plugin+'.model') + _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())) except Exception as e: