From 91f4e91272f8069dc00105650e2e1964605f8b5c Mon Sep 17 00:00:00 2001 From: Saeed Rasooli Date: Thu, 2 Jan 2025 00:06:47 +0330 Subject: [PATCH] add pyproject.toml and fix ruff errors --- pyproject.toml | 129 ++++++++++++++++++++++++++++ s_tui/about_menu.py | 6 +- s_tui/help_menu.py | 5 +- s_tui/helper_functions.py | 25 +++--- s_tui/s_tui.py | 113 ++++++++++++------------ s_tui/sensors_menu.py | 13 +-- s_tui/sources/fan_source.py | 4 +- s_tui/sources/freq_source.py | 6 +- s_tui/sources/hook_script.py | 3 +- s_tui/sources/rapl_power_source.py | 4 +- s_tui/sources/rapl_read.py | 15 ++-- s_tui/sources/script_hook_loader.py | 1 + s_tui/sources/source.py | 2 +- s_tui/sources/temp_source.py | 10 +-- s_tui/sources/util_source.py | 1 + s_tui/stress_menu.py | 35 ++++---- s_tui/sturwid/bar_graph_vector.py | 12 ++- s_tui/sturwid/complex_bar_graph.py | 16 ++-- s_tui/sturwid/summary_text_list.py | 7 +- s_tui/sturwid/ui_elements.py | 6 +- s_tui/tests/test_util_source.py | 1 + setup.py | 3 +- 22 files changed, 274 insertions(+), 143 deletions(-) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1a28413 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,129 @@ +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "lf" +docstring-code-format = false +exclude = [] + +[tool.ruff] +line-length = 88 +target-version = "py310" + +# Exclude a variety of commonly ignored directories. +exclude = [ + "whitelist.py", # for vulture + ".direnv", + ".eggs", + ".git", + ".mypy_cache", + ".nox", + ".pants.d", + ".ruff_cache", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "venv", +] + +[tool.ruff.lint] +select = [ + # "ANN", # flake8-annotationsq + "F", # Pyflakes + "E", # pycodestyle Error + "W", # pycodestyle Warning + # "C90", # mccabe: C901: {name} is too complex ({complexity}) + "I", # isort: unsorted-imports, missing-required-import + # "D", # pydocstyle + "B", # flake8-bugbear + # "UP", # pyupgrade + # "YTT", # flake8-2020 + "ASYNC1", # flake8-trio + "BLE", # flake8-blind-except + "B", # flake8-bugbear + "A", # flake8-builtins + "COM", # flake8-commas + # "CPY", # flake8-copyright --preview + "C4", # flake8-comprehensions + "DTZ", # flake8-datetimez + "T10", # flake8-debugger + "DJ", # flake8-django + # "EXE", # flake8-executable + "FA", # flake8-future-annotations + "ISC", # flake8-implicit-str-concat + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "INP", # flake8-no-pep420 + "PIE", # flake8-pie + # "T20", # flake8-print + # "PYI", # flake8-pyi + "PT", # flake8-pytest-style + "Q", # flake8-quotes + "RSE", # flake8-raise + "RET", # flake8-return + "SLF", # flake8-self + "SLOT", # flake8-slots + "SIM", # flake8-simplify + "TID", # flake8-tidy-imports + "TCH", # flake8-type-checking + "INT", # flake8-gettext + # "ARG", # flake8-unused-arguments + # "PTH", # flake8-use-pathlib + "PD", # pandas-vet + "PGH", # pygrep-hooks + "PL", # Pylint + # "TRY", # tryceratops, they all sound BS + # "FLY", # flynt + "NPY", # NumPy-specific rules + "AIR", # Airflow + # "PERF", # Perflint + "FURB", # refurb --preview + "LOG", # flake8-logging + "RUF", # Ruff-specific rules +] +ignore = [ + "PLR6301", # Method `...` could be a function, class method, or static method + "LOG015", # `debug()` call on root logger + "COM812", # Trailing comma missing + "SLF", # Private member accessed + "DTZ005", # The use of `datetime.datetime.now()` without `tz` argument is not allowed + "PLR0913", # Too many arguments in function definition + "PLR0914", # Too many local variables + "PLR0915", # Too many statements + "PLR0917", # Too many positional arguments + "FURB101", # `open` and `read` should be replaced by `Path(rootConfJsonFile).read_text()` + "FURB103", # `open` and `write` should be replaced by `Path(... + "PLR2004", # Magic value used in comparison, consider replacing `...` with a constant variable + "RUF005", # Consider `[*_list, x]` instead of concatenation + "PT009", # Use a regular `assert` instead of unittest-style `assertEqual`, why? + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D107", # Missing docstring in `__init__` + "D205", # 1 blank line required between summary line and description + "D211", # (Do not enable) no-blank-line-before-class + "D212", # multi-line-summary-first-line, conflicts with D213:multi-line-summary-second-line + "D401", # First line of docstring should be in imperative mood + "D417", # Missing argument descriptions in the docstring + "E402", # Module level import not at top of file + "SIM105", # Use contextlib.suppress({exception}) instead of try-except-pass + "SIM117", # Use a single with statement with multiple contexts... + "SIM115", # Use context handler for opening files +] + +# Allow autofix for all enabled rules (when `--fix`) is provided. +unfixable = [] + + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +mccabe.max-complexity = 13 # Unlike Flake8, default to a complexity level of 10. + diff --git a/s_tui/about_menu.py b/s_tui/about_menu.py index df57504..7012c59 100644 --- a/s_tui/about_menu.py +++ b/s_tui/about_menu.py @@ -17,12 +17,12 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """Displays the About message menu """ -from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import, print_function import urwid -from s_tui.sturwid.ui_elements import ViListBox + from s_tui.helper_functions import __version__ +from s_tui.sturwid.ui_elements import ViListBox ABOUT_MESSAGE = """ s-tui is a monitoring tool for your CPU's temperature, frequency, utilization \ diff --git a/s_tui/help_menu.py b/s_tui/help_menu.py index 522ca33..236bd78 100644 --- a/s_tui/help_menu.py +++ b/s_tui/help_menu.py @@ -19,9 +19,10 @@ """A class display the help message menu """ -from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import, print_function + import urwid + from s_tui.sturwid.ui_elements import ViListBox HELP_MESSAGE = """ diff --git a/s_tui/helper_functions.py b/s_tui/helper_functions.py index fca51f8..9a0d3ed 100644 --- a/s_tui/helper_functions.py +++ b/s_tui/helper_functions.py @@ -18,16 +18,15 @@ """ Helper functions module with common useful functions """ -import os +import csv +import json import logging +import os import platform -import subprocess import re -import csv +import subprocess import sys -import json import time - from collections import OrderedDict __version__ = "1.1.6" @@ -52,7 +51,7 @@ def get_processor_name(): all_info = cpuinfo.readlines() for line in all_info: if b"model name" in line: - return re.sub(b".*model name.*:", b"", line, 1) + return re.sub(rb".*model name.*:", b"", line, count=1) elif platform.system() == "FreeBSD": cmd = ["sysctl", "-n", "hw.model"] process = subprocess.Popen( @@ -60,8 +59,7 @@ def get_processor_name(): stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) - str_value = process.stdout.read() - return str_value + return process.stdout.read() elif platform.system() == "Darwin": cmd = ["sysctl", "-n", "machdep.cpu.brand_string"] process = subprocess.Popen( @@ -69,8 +67,7 @@ def get_processor_name(): stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) - str_value = process.stdout.read() - return str_value + return process.stdout.read() return platform.processor() @@ -92,14 +89,14 @@ def output_to_csv(sources, csv_writeable_file): """Print statistics to csv file""" file_exists = os.path.isfile(csv_writeable_file) - with open(csv_writeable_file, "a") as csvfile: + with open(csv_writeable_file, "a", encoding="utf-8") as csvfile: csv_dict = OrderedDict() csv_dict.update({"Time": time.strftime("%Y-%m-%d_%H:%M:%S")}) summaries = [val for key, val in sources.items()] for summarie in summaries: - update_dict = dict() - for prob, val in summarie.source.get_sensors_summary().items(): - prob = summarie.source.get_source_name() + ":" + prob + update_dict = {} + for prob_, val in summarie.source.get_sensors_summary().items(): + prob = summarie.source.get_source_name() + ":" + prob_ update_dict[prob] = val csv_dict.update(update_dict) diff --git a/s_tui/s_tui.py b/s_tui/s_tui.py index f014786..01aa7a6 100755 --- a/s_tui/s_tui.py +++ b/s_tui/s_tui.py @@ -23,16 +23,15 @@ from __future__ import absolute_import import argparse -import signal import itertools import logging import os +import signal import subprocess +import sys import time import timeit -from collections import OrderedDict -from collections import defaultdict -import sys +from collections import OrderedDict, defaultdict import psutil import urwid @@ -45,42 +44,40 @@ # Menus from s_tui.about_menu import AboutMenu -from s_tui.help_menu import HelpMenu -from s_tui.help_menu import HELP_MESSAGE -from s_tui.stress_menu import StressMenu -from s_tui.sensors_menu import SensorsMenu +from s_tui.help_menu import HELP_MESSAGE, HelpMenu # Helpers -from s_tui.helper_functions import __version__ -from s_tui.helper_functions import get_processor_name -from s_tui.helper_functions import kill_child_processes -from s_tui.helper_functions import output_to_csv -from s_tui.helper_functions import output_to_terminal -from s_tui.helper_functions import output_to_json -from s_tui.helper_functions import get_user_config_dir -from s_tui.helper_functions import get_user_config_file -from s_tui.helper_functions import make_user_config_dir -from s_tui.helper_functions import user_config_dir_exists -from s_tui.helper_functions import user_config_file_exists -from s_tui.helper_functions import seconds_to_text -from s_tui.helper_functions import str_to_bool -from s_tui.helper_functions import which +from s_tui.helper_functions import ( + __version__, + get_processor_name, + get_user_config_dir, + get_user_config_file, + kill_child_processes, + make_user_config_dir, + output_to_csv, + output_to_json, + output_to_terminal, + seconds_to_text, + str_to_bool, + user_config_dir_exists, + user_config_file_exists, + which, +) +from s_tui.sensors_menu import SensorsMenu +from s_tui.sources.fan_source import FanSource +from s_tui.sources.freq_source import FreqSource +from s_tui.sources.rapl_power_source import RaplPowerSource +from s_tui.sources.script_hook_loader import ScriptHookLoader +from s_tui.sources.temp_source import TempSource -# Ui Elements -from s_tui.sturwid.ui_elements import ViListBox -from s_tui.sturwid.ui_elements import radio_button -from s_tui.sturwid.ui_elements import button -from s_tui.sturwid.ui_elements import DEFAULT_PALETTE +# Sources +from s_tui.sources.util_source import UtilSource +from s_tui.stress_menu import StressMenu from s_tui.sturwid.bar_graph_vector import BarGraphVector from s_tui.sturwid.summary_text_list import SummaryTextList -# Sources -from s_tui.sources.util_source import UtilSource -from s_tui.sources.freq_source import FreqSource -from s_tui.sources.temp_source import TempSource -from s_tui.sources.rapl_power_source import RaplPowerSource -from s_tui.sources.fan_source import FanSource -from s_tui.sources.script_hook_loader import ScriptHookLoader +# Ui Elements +from s_tui.sturwid.ui_elements import DEFAULT_PALETTE, ViListBox, button, radio_button UPDATE_INTERVAL = 1 HOOK_INTERVAL = 30 * 1000 @@ -111,13 +108,13 @@ class MainLoop(urwid.MainLoop): def signal_handler(self, frame): """signal handler for properly exiting Ctrl+C""" graph_controller.stress_controller.kill_stress_process() - raise urwid.ExitMainLoop() + raise urwid.ExitMainLoop def unhandled_input(self, uinput): logging.debug("Caught %s", uinput) if uinput == "q": graph_controller.stress_controller.kill_stress_process() - raise urwid.ExitMainLoop() + raise urwid.ExitMainLoop if uinput == "f1": graph_controller.view.on_help_menu_open(graph_controller.view.main_window_w) @@ -176,7 +173,7 @@ def kill_stress_process(self): def start_stress(self, stress_cmd): """Starts a new stress process with a given cmd""" - with open(os.devnull, "w") as dev_null: + with open(os.devnull, "w", encoding="utf-8") as dev_null: try: stress_proc = subprocess.Popen( stress_cmd, stdout=dev_null, stderr=dev_null @@ -265,7 +262,6 @@ def update_displayed_information(self): graph.update() except IndexError: logging.debug("Graph update failed") - pass # update graph summery for summary in self.visible_summaries.values(): @@ -273,7 +269,6 @@ def update_displayed_information(self): summary.update() except IndexError: logging.debug("Summary update failed") - pass # Only update clock if not is stress mode if self.controller.stress_controller.get_current_mode() != "Monitor": @@ -433,16 +428,20 @@ def _generate_graph_controls(self): self.mode_buttons[0].set_state(True, do_callback=False) # Create list of buttons - control_options = list() - control_options.append(button("Graphs", self.on_graphs_menu_open)) - control_options.append(button("Summaries", self.on_summary_menu_open)) + control_options = [] + control_options.extend(( + button("Graphs", self.on_graphs_menu_open), + button("Summaries", self.on_summary_menu_open), + )) if self.controller.stress_exe: control_options.append(button("Stress Options", self.on_stress_menu_open)) - control_options.append(button("Reset", self.on_reset_button)) - control_options.append(button("Help", self.on_help_menu_open)) - control_options.append(button("About", self.on_about_menu_open)) - control_options.append(button("Save Settings", self.on_save_settings)) - control_options.append(button("Quit", self.on_exit_program)) + control_options.extend(( + button("Reset", self.on_reset_button), + button("Help", self.on_help_menu_open), + button("About", self.on_about_menu_open), + button("Save Settings", self.on_save_settings), + button("Quit", self.on_exit_program), + )) # Create the menu animate_controls = urwid.GridFlow(control_options, 18, 2, 0, "center") @@ -556,7 +555,7 @@ def main_window(self): ) # Do not show the graph if there is no selected sensors - for key in self.graphs.keys(): + for key in self.graphs: if not any(self.graphs_menu.active_sensors[key]): del self.visible_graphs[key] @@ -609,7 +608,8 @@ class GraphController: visa versa """ - def _load_config(self, t_thresh): + # PLR0912 Too many branches (17 > 12) + def _load_config(self, t_thresh): # noqa: PLR0912 """ Uses configurations defined by user to configure sources for display. This should be the only place where sources are initiated @@ -804,7 +804,7 @@ def main(self): # In case of Zero division, we want an error to return, and # get a clue where this happens logging.debug("Some stat caused divide by zero exception. Exiting") - logging.error(err, exc_info=True) + logging.exception(err) print(ERROR_MESSAGE) except AttributeError as err: # In this case we restart the loop, to address bug #50, where @@ -816,7 +816,7 @@ def main(self): # This might happen if the stress process is not found, in this # case, we want to know why logging.error("No such process error") - logging.error(err, exc_info=True) + logging.exception(err) print(ERROR_MESSAGE) def update_stress_mode(self): @@ -854,7 +854,7 @@ def _save_displayed_setting(conf, submenu): logging.debug("Saving settings for %s", source) logging.debug("Visible sensors %s", visible_sensors) # TODO: consider changing sensors_list to dict - curr_sensor = [x for x in sources if x.get_source_name() == source][0] + curr_sensor = next(x for x in sources if x.get_source_name() == source) sensor_list = curr_sensor.get_sensor_list() for sensor_id, sensor in enumerate(sensor_list): try: @@ -867,7 +867,7 @@ def _save_displayed_setting(conf, submenu): conf = configparser.ConfigParser() config_file = get_user_config_file() - with open(config_file, "w") as cfgfile: + with open(config_file, "w", encoding="utf-8") as cfgfile: conf.add_section("GraphControl") # Save the configured refresh rete conf.set("GraphControl", "refresh", str(self.refresh_rate)) @@ -884,7 +884,7 @@ def _save_displayed_setting(conf, submenu): def exit_program(self): """Kill all stress operations upon exit""" self.stress_controller.kill_stress_process() - raise urwid.ExitMainLoop() + raise urwid.ExitMainLoop def animate_graph(self, loop, user_data=None): """ @@ -954,7 +954,7 @@ def main(): elif args.json: output_to_json(sources) - global graph_controller + global graph_controller # noqa: PLW0603 graph_controller = GraphController(args) graph_controller.main() @@ -1029,8 +1029,7 @@ def get_args(): default="2.0", help="Refresh rate in seconds. Default: 2.0", ) - args = parser.parse_args() - return args + return parser.parse_args() if __name__ == "__main__": diff --git a/s_tui/sensors_menu.py b/s_tui/sensors_menu.py index 1958bb0..21958d3 100644 --- a/s_tui/sensors_menu.py +++ b/s_tui/sensors_menu.py @@ -20,11 +20,12 @@ A class displaying all available sensors """ -from __future__ import print_function -from __future__ import absolute_import +from __future__ import absolute_import, print_function + import copy import urwid + from s_tui.sturwid.ui_elements import ViListBox @@ -72,7 +73,9 @@ def __init__(self, return_fn, source_list, default_source_conf): # create the checkbox buttons with the saved visibility for sensor, s_tatus in zip( - source.get_sensor_list(), self.sensor_status_dict[source_name] + source.get_sensor_list(), + self.sensor_status_dict[source_name], + strict=False, ): cb = urwid.CheckBox(sensor, s_tatus) self.sensor_button_dict[source_name].append(cb) @@ -92,7 +95,7 @@ def __init__(self, return_fn, source_list, default_source_conf): self.main_window = urwid.LineBox(ViListBox(listw)) max_height = 6 - for sensor, s_tatus in self.active_sensors.items(): + for s_tatus in self.active_sensors.values(): max_height = max(max_height, len(s_tatus) + 6) self.size = max_height, self.MAX_TITLE_LEN @@ -103,7 +106,7 @@ def get_size(self): def set_checkbox_value(self): for sensor, sensor_cb in self.sensor_button_dict.items(): sensor_cb_next_state = self.active_sensors[sensor] - for checkbox, state in zip(sensor_cb, sensor_cb_next_state): + for checkbox, state in zip(sensor_cb, sensor_cb_next_state, strict=False): checkbox.set_state(state) def on_cancel(self, w): diff --git a/s_tui/sources/fan_source.py b/s_tui/sources/fan_source.py index a5e756a..4f6e913 100644 --- a/s_tui/sources/fan_source.py +++ b/s_tui/sources/fan_source.py @@ -21,7 +21,9 @@ from __future__ import absolute_import import logging + import psutil + from s_tui.sources.source import Source @@ -43,7 +45,7 @@ def __init__(self): self.measurement_unit = "RPM" self.pallet = ("fan light", "fan dark", "fan light smooth", "fan dark smooth") - sensors_dict = dict() + sensors_dict = {} try: sensors_dict = psutil.sensors_fans() except IOError: diff --git a/s_tui/sources/freq_source.py b/s_tui/sources/freq_source.py index cd86bd2..6e5c23b 100644 --- a/s_tui/sources/freq_source.py +++ b/s_tui/sources/freq_source.py @@ -19,6 +19,7 @@ from __future__ import absolute_import import logging + import psutil from s_tui.sources.source import Source @@ -54,10 +55,9 @@ def __init__(self): self.top_freq = psutil.cpu_freq().max self.max_freq = self.top_freq - if self.top_freq == 0.0: + if self.top_freq == 0.0 and max(self.last_measurement) >= 0: # If top freq not available, take the current as top - if max(self.last_measurement) >= 0: - self.max_freq = max(self.last_measurement) + self.max_freq = max(self.last_measurement) self.available_sensors = ["Avg"] for core_id, _ in enumerate(psutil.cpu_freq(True)): diff --git a/s_tui/sources/hook_script.py b/s_tui/sources/hook_script.py index 2504cc5..c2b1188 100644 --- a/s_tui/sources/hook_script.py +++ b/s_tui/sources/hook_script.py @@ -18,6 +18,7 @@ import os import subprocess + from s_tui.sources.hook import Hook @@ -40,7 +41,7 @@ def _run_script(self, *args): # Run script in a shell subprocess asynchronously so # as to not block main thread (graphs) # if the script is a long-running task - with open(os.devnull, "w") as dev_null: + with open(os.devnull, "w", encoding="utf-8") as dev_null: subprocess.Popen( ["/bin/sh", args[0][0]], # TODO -- Could redirect this to a separate log diff --git a/s_tui/sources/rapl_power_source.py b/s_tui/sources/rapl_power_source.py index b08a0b2..0534f71 100644 --- a/s_tui/sources/rapl_power_source.py +++ b/s_tui/sources/rapl_power_source.py @@ -21,11 +21,11 @@ from __future__ import absolute_import -import time import logging +import time -from s_tui.sources.source import Source from s_tui.sources.rapl_read import get_power_reader +from s_tui.sources.source import Source LOGGER = logging.getLogger(__name__) diff --git a/s_tui/sources/rapl_read.py b/s_tui/sources/rapl_read.py index c5dde5d..f806fe1 100644 --- a/s_tui/sources/rapl_read.py +++ b/s_tui/sources/rapl_read.py @@ -19,15 +19,15 @@ from __future__ import absolute_import -import logging import glob +import logging import os import re from collections import namedtuple from multiprocessing import cpu_count from sys import byteorder -from s_tui.helper_functions import cat +from s_tui.helper_functions import cat INTER_RAPL_DIR = "/sys/class/powercap/intel-rapl/" AMD_ENERGY_DIR_GLOB = "/sys/devices/platform/amd_energy.0/hwmon/hwmon*/" @@ -46,13 +46,13 @@ class RaplReader: def __init__(self): basenames = glob.glob("/sys/class/powercap/intel-rapl:*/") - self.basenames = sorted(set({x for x in basenames})) + self.basenames = sorted(set(basenames)) def read_power(self): """Read power stats and return dictionary""" pjoin = os.path.join - ret = list() + ret = [] for path in self.basenames: name = None try: @@ -86,7 +86,7 @@ def __init__(self): glob.glob(AMD_ENERGY_DIR_GLOB + "energy*_label") ) ), - sorted(glob.glob(AMD_ENERGY_DIR_GLOB + "energy*_input")), + sorted(glob.glob(AMD_ENERGY_DIR_GLOB + "energy*_input")), strict=False, ) ) @@ -103,8 +103,7 @@ def get_input_position(label, socket_number): num = int(AMDEnergyReader.match_label(label).group(2)) if "socket" in label: return num - else: - return num + socket_number + return num + socket_number def read_power(self): ret = [] @@ -215,7 +214,7 @@ def available(): # Check whether MSRs are available and we have permission to read them try: - open("/dev/cpu/0/msr") + open("/dev/cpu/0/msr", encoding="utf-8") return True except (FileNotFoundError, PermissionError): return False diff --git a/s_tui/sources/script_hook_loader.py b/s_tui/sources/script_hook_loader.py index 4e8088e..911378d 100644 --- a/s_tui/sources/script_hook_loader.py +++ b/s_tui/sources/script_hook_loader.py @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import os + from s_tui.sources.hook_script import ScriptHook diff --git a/s_tui/sources/source.py b/s_tui/sources/source.py index bb861e9..62de923 100644 --- a/s_tui/sources/source.py +++ b/s_tui/sources/source.py @@ -17,8 +17,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ This module implements a parent source class for s-tui""" -from collections import OrderedDict import logging +from collections import OrderedDict class Source: diff --git a/s_tui/sources/temp_source.py b/s_tui/sources/temp_source.py index 7c918e5..ee9c8ae 100644 --- a/s_tui/sources/temp_source.py +++ b/s_tui/sources/temp_source.py @@ -19,9 +19,10 @@ from __future__ import absolute_import -import warnings import logging +import warnings from collections import OrderedDict + import psutil from s_tui.sources.source import Source @@ -95,10 +96,9 @@ def __init__(self, temp_thresh=None): # Set temperature threshold if a custom one is set self.temp_thresh = self.THRESHOLD_TEMP - if temp_thresh is not None: - if int(temp_thresh) > 0: - self.temp_thresh = int(temp_thresh) - logging.debug("Updated custom threshold to %s", self.temp_thresh) + if temp_thresh is not None and int(temp_thresh) > 0: + self.temp_thresh = int(temp_thresh) + logging.debug("Updated custom threshold to %s", self.temp_thresh) def update(self): sample = OrderedDict(sorted(psutil.sensors_temperatures().items())) diff --git a/s_tui/sources/util_source.py b/s_tui/sources/util_source.py index 455ec3f..cc6a639 100644 --- a/s_tui/sources/util_source.py +++ b/s_tui/sources/util_source.py @@ -19,6 +19,7 @@ from __future__ import absolute_import import logging + import psutil from s_tui.sources.source import Source diff --git a/s_tui/stress_menu.py b/s_tui/stress_menu.py index 73cc61f..e789ff4 100644 --- a/s_tui/stress_menu.py +++ b/s_tui/stress_menu.py @@ -20,8 +20,9 @@ """ from __future__ import print_function -import re + import logging +import re import psutil import urwid @@ -181,39 +182,35 @@ def on_cancel(self, _): def get_stress_cmd(self): stress_cmd = [self.stress_exe] if int(self.sqrt_workers) > 0: - stress_cmd.append("-c") - stress_cmd.append(self.sqrt_workers) + stress_cmd.extend(("-c", self.sqrt_workers)) if int(self.sync_workers) > 0: - stress_cmd.append("-i") - stress_cmd.append(self.sync_workers) + stress_cmd.extend(("-i", self.sync_workers)) if int(self.memory_workers) > 0: - stress_cmd.append("--vm") - stress_cmd.append(self.memory_workers) - stress_cmd.append("--vm-bytes") - stress_cmd.append(self.malloc_byte) - stress_cmd.append("--vm-stride") - stress_cmd.append(self.byte_touch_cnt) + stress_cmd.extend(( + "--vm", self.memory_workers, + "--vm-bytes", self.malloc_byte, + "--vm-stride", self.byte_touch_cnt, + )) if self.no_malloc: stress_cmd.append("--vm-keep") if int(self.write_workers) > 0: - stress_cmd.append("--hdd") - stress_cmd.append(self.write_workers) - stress_cmd.append("--hdd-bytes") - stress_cmd.append(self.write_bytes) + stress_cmd.extend(( + "--hdd", self.write_workers, + "--hdd-bytes", self.write_bytes, + )) if self.time_out != "none": - stress_cmd.append("-t") - stress_cmd.append(self.time_out) + stress_cmd.extend(("-t", self.time_out)) return stress_cmd @staticmethod def get_pos_num(num, default): - num_valid = re.match(r"\A([0-9]+)\Z", num, re.I) + num_valid = re.match(r"\A([0-9]+)\Z", num, re.IGNORECASE) if num_valid or (num == "none" and default == "none"): return num return default @@ -222,7 +219,7 @@ def get_pos_num(num, default): def get_valid_byte(num, default): """check if the format of number is (num)(G|m|B) i.e 500GB, 200mb. 400 etc..""" - num_valid = re.match(r"\A([0-9]+)(M|G|m|g|)(B|b|\b)\Z", num, re.I) + num_valid = re.match(r"\A([0-9]+)(M|G|m|g|)(B|b|\b)\Z", num, re.IGNORECASE) if num_valid: return num return default diff --git a/s_tui/sturwid/bar_graph_vector.py b/s_tui/sturwid/bar_graph_vector.py index e2231cd..50c3a3c 100644 --- a/s_tui/sturwid/bar_graph_vector.py +++ b/s_tui/sturwid/bar_graph_vector.py @@ -18,11 +18,11 @@ from __future__ import absolute_import -from s_tui.sturwid.complex_bar_graph import LabeledBarGraphVector -from s_tui.sturwid.complex_bar_graph import ScalableBarGraph import logging import math +from s_tui.sturwid.complex_bar_graph import LabeledBarGraphVector, ScalableBarGraph + logger = logging.getLogger(__name__) @@ -116,10 +116,7 @@ def get_is_available(self): def get_label_scale(self, min_val, max_val, size): """Dynamically change the scale of the graph (y label)""" - if size < self.SCALE_DENSITY: - label_cnt = 1 - else: - label_cnt = int(size / self.SCALE_DENSITY) + label_cnt = 1 if size < self.SCALE_DENSITY else int(size / self.SCALE_DENSITY) try: if max_val >= 100: label = [ @@ -147,7 +144,8 @@ def set_smooth_colors(self, smooth): ["bg background", self.color_a, self.color_b], satt=self.satt ) - def update(self): + # PLR0912 Too many branches (20 > 12) + def update(self): # noqa: PLR0912 if not self.get_is_available(): return diff --git a/s_tui/sturwid/complex_bar_graph.py b/s_tui/sturwid/complex_bar_graph.py index f1a46f1..68abe23 100644 --- a/s_tui/sturwid/complex_bar_graph.py +++ b/s_tui/sturwid/complex_bar_graph.py @@ -136,15 +136,17 @@ def set_visible_graphs(self, visible_graph_list=None): graph_vector_column_list = [] for state, graph, sub_title in zip( - visible_graph_list, self.bar_graph_vector, self.sub_title_list + visible_graph_list, self.bar_graph_vector, self.sub_title_list, strict=False ): if state: text_w = urwid.Text(sub_title, align="center") sub_title_widget = urwid.ListBox([text_w]) graph_a = [("fixed", 1, sub_title_widget), ("weight", 1, graph)] graph_and_title = urwid.Pile(graph_a) - graph_vector_column_list.append(("weight", 1, graph_and_title)) - graph_vector_column_list.append(("fixed", 1, vline)) + graph_vector_column_list.extend(( + ("weight", 1, graph_and_title), + ("fixed", 1, vline), + )) # if all sub graph are disabled if not graph_vector_column_list: @@ -172,7 +174,7 @@ def set_graph(self, graph_vector): @staticmethod def check_label(label): - if len(label) >= 2 and not (None in label) or not label or label is None: - return True - - return False + return bool( + (len(label) >= 2 and None not in label) + or not label or label is None + ) diff --git a/s_tui/sturwid/summary_text_list.py b/s_tui/sturwid/summary_text_list.py index 760df91..014a657 100644 --- a/s_tui/sturwid/summary_text_list.py +++ b/s_tui/sturwid/summary_text_list.py @@ -16,9 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -import urwid from collections import OrderedDict +import urwid + class SummaryTextList: MAX_LABEL_L = 12 @@ -30,7 +31,7 @@ def __init__(self, source, visible_sensors_list): # The title is the first in the list self.visible_summaries[keys[0]] = any(visible_sensors_list) # All others according to initial visibility - for key, visible in zip(keys[1:], visible_sensors_list): + for key, visible in zip(keys[1:], visible_sensors_list, strict=False): self.visible_summaries[key] = visible # We keep a dict of all the items in the summary list @@ -58,7 +59,7 @@ def update_visibility(self, visible_sensors): keys = list(self.visible_summaries.keys()) self.visible_summaries[keys[0]] = any(visible_sensors) # Do not change visibility of title - for sensor, visible in zip(keys[1:], visible_sensors): + for sensor, visible in zip(keys[1:], visible_sensors, strict=False): self.visible_summaries[sensor] = visible def update(self): diff --git a/s_tui/sturwid/ui_elements.py b/s_tui/sturwid/ui_elements.py index 9ea6725..7de2f62 100644 --- a/s_tui/sturwid/ui_elements.py +++ b/s_tui/sturwid/ui_elements.py @@ -92,11 +92,9 @@ def keypress(self, size, key): def radio_button(group, label, fn): """Inheriting radio button of urwid""" w = urwid.RadioButton(group, label, False, on_state_change=fn) - w = urwid.AttrWrap(w, "button normal", "button select") - return w + return urwid.AttrWrap(w, "button normal", "button select") def button(t, fn, data=None): w = urwid.Button(t, fn, data) - w = urwid.AttrWrap(w, "button normal", "button select") - return w + return urwid.AttrWrap(w, "button normal", "button select") diff --git a/s_tui/tests/test_util_source.py b/s_tui/tests/test_util_source.py index 15dd49e..dc0139e 100644 --- a/s_tui/tests/test_util_source.py +++ b/s_tui/tests/test_util_source.py @@ -1,4 +1,5 @@ import unittest + from s_tui.sources.util_source import UtilSource diff --git a/setup.py b/setup.py index 03838b0..53fec37 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ from __future__ import absolute_import from setuptools import setup + import s_tui.helper_functions as AUX setup( @@ -26,7 +27,7 @@ author="Alex Manuskin", author_email="amanusk@pm.me", description="Stress Terminal UI stress test and monitoring tool", - long_description=open("README.md", "r").read(), + long_description=open("README.md", "r", encoding="utf-8").read(), long_description_content_type="text/markdown", license="GPLv2", url="https://github.com/amanusk/s-tui",