From b491cbe42ba9a18fb6af006a9e4767638815916a Mon Sep 17 00:00:00 2001 From: nicolargo Date: Thu, 26 Dec 2024 10:48:50 +0100 Subject: [PATCH] Make main.py comliant with PyTest (concerning args) --- Makefile | 57 +++----- dev-requirements.txt | 1 + glances/main.py | 131 +++++++++--------- glances/plugins/gpu/__init__.py | 2 +- glances/plugins/gpu/cards/amd.py | 2 +- pyproject.toml | 2 +- {test-data => tests-data}/issues/issue2849.py | 0 .../class/drm/card0/device/gpu_busy_percent | 0 .../drm/card0/device/hwmon/hwmon0/temp1_input | 0 .../drm/card0/device/mem_info_vram_total | 0 .../class/drm/card0/device/mem_info_vram_used | 0 .../sys/class/drm/card0/device/pp_dpm_mclk | 0 .../sys/class/drm/card0/device/pp_dpm_sclk | 0 .../amd/sys/kernel/debug/dri/0/amdgpu_pm_info | 0 unittest-core.py | 2 +- 15 files changed, 94 insertions(+), 103 deletions(-) rename {test-data => tests-data}/issues/issue2849.py (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/gpu_busy_percent (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_total (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_used (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_mclk (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_sclk (100%) rename {test-data => tests-data}/plugins/gpu/amd/sys/kernel/debug/dri/0/amdgpu_pm_info (100%) diff --git a/Makefile b/Makefile index 18faee2d..9db07841 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ PORT ?= 8008 venv_full:= venv/bin -venv_dev := venv-dev/bin venv_min := venv-min/bin CONF := conf/glances.conf PIP := $(venv_full)/pip PYTHON := $(venv_full)/python +PYTEST := $(venv_full)/python -m pytest LASTTAG = $(shell git describe --tags --abbrev=0) -VENV_TYPES := full min dev +VENV_TYPES := full min VENV_PYTHON := $(VENV_TYPES:%=venv-%-python) VENV_UPG := $(VENV_TYPES:%=venv-%-upgrade) VENV_DEPS := $(VENV_TYPES:%=venv-%) @@ -30,7 +30,7 @@ DOCKER_OPTS := --rm -e TZ="${TZ}" -e GLANCES_OPT="" --pid host --network h # if the command is only `make`, the default tasks will be the printing of the help. .DEFAULT_GOAL := help -.PHONY: help test docs docs-server venv venv-min venv-dev +.PHONY: help test docs docs-server venv venv-min help: ## List all make commands available @grep -E '^[\.a-zA-Z_%-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ @@ -53,7 +53,7 @@ endef $(foreach TYPE,$(VENV_TYPES),$(eval $(DEFINE_VARS_FOR_TYPE))) $(VENV_PYTHON): venv-%-python: - virtualenv -p /usr/bin/python3 $(if $(filter full,$*),venv,venv-$*) + virtualenv -p python3 $(if $(filter full,$*),venv,venv-$*) $(VENV_INST_UPG): venv-%: $(if $(UPGRADE),$(VIRTUAL_ENV)/pip install --upgrade pip,) @@ -66,43 +66,32 @@ venv-upgrade: $(VENV_UPG) ## Upgrade all Python 3 dependencies # For full installation (with optional dependencies) -venv-full venv-full-upgrade: REQS = requirements.txt optional-requirements.txt +venv-full venv-full-upgrade: REQS = requirements.txt optional-requirements.txt dev-requirements.txt doc-requirements.txt venv-full-python: ## Install Python 3 venv venv-full: venv-python ## Install Python 3 run-time venv-full-upgrade: ## Upgrade Python 3 run-time dependencies +venv-full: PRE_COMMIT = 1 # For minimal installation (without optional dependencies) -venv-min venv-min-upgrade: REQS = requirements.txt +venv-min venv-min-upgrade: REQS = requirements.txt dev-requirements.txt doc-requirements.txt venv-min-python: ## Install Python 3 venv minimal venv-min: venv-min-python ## Install Python 3 minimal run-time dependencies venv-min-upgrade: ## Upgrade Python 3 minimal run-time dependencies -# For development - -venv-dev venv-dev-upgrade: REQS = dev-requirements.txt doc-requirements.txt -venv-dev: PRE_COMMIT = 1 - -venv-dev-python: ## Install Python 3 venv -venv-dev: venv-python ## Install Python 3 dev dependencies -venv-dev-upgrade: ## Upgrade Python 3 dev dependencies - # =================================================================== # Tests # =================================================================== -$(UNIT_TESTS): test-%: unittest-%.py - $(PYTHON) $< +test: ## Run unit tests + $(PYTEST) -test-core: ## Run core unit tests -test-restful: ## Run Restful unit tests -test-xmlrpc: ## Run XMLRPC unit tests +test-core: ## Run Core unit tests + $(PYTEST) tests/test_core.py -test: $(UNIT_TESTS) ## Run unit tests - -test-with-upgrade: venv-upgrade venv-dev-upgrade test ## Upgrade deps and run unit tests +test-with-upgrade: venv-upgrade test ## Upgrade deps and run unit tests test-min: ## Run core unit tests in minimal environment $(venv_min)/python unittest-core.py @@ -115,16 +104,16 @@ test-min-with-upgrade: venv-min-upgrade ## Upgrade deps and run unit tests in mi # =================================================================== format: ## Format the code - $(venv_dev)/python -m ruff format . + $(venv_full)/python -m ruff format . lint: ## Lint the code. - $(venv_dev)/python -m ruff check . --fix + $(venv_full)/python -m ruff check . --fix codespell: ## Run codespell to fix common misspellings in text files - $(venv_dev)/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics -w + $(venv_full)/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics -w semgrep: ## Run semgrep to find bugs and enforce code standards - $(venv_dev)/semgrep scan --config=auto + $(venv_full)/semgrep scan --config=auto profiling-%: SLEEP = 3 profiling-%: TIMES = 30 @@ -139,7 +128,7 @@ profiling-gprof: CPROF = glances.cprof profiling-gprof: ## Callgraph profiling (need "apt install graphviz") $(DISPLAY-BANNER) $(PYTHON) -m cProfile -o $(CPROF) run-venv.py --stop-after $(TIMES) - $(venv_dev)/gprof2dot -f pstats $(CPROF) | dot -Tsvg -o $(OUT_DIR)/glances-cgraph.svg + $(venv_full)/gprof2dot -f pstats $(CPROF) | dot -Tsvg -o $(OUT_DIR)/glances-cgraph.svg rm -f $(CPROF) profiling-pyinstrument: ## PyInstrument profiling @@ -149,7 +138,7 @@ profiling-pyinstrument: ## PyInstrument profiling profiling-pyspy: ## Flame profiling $(DISPLAY-BANNER) - $(venv_dev)/py-spy record -o $(OUT_DIR)/glances-flame.svg -d 60 -s -- $(PYTHON) run-venv.py --stop-after $(TIMES) + $(venv_full)/py-spy record -o $(OUT_DIR)/glances-flame.svg -d 60 -s -- $(PYTHON) run-venv.py --stop-after $(TIMES) profiling: profiling-gprof profiling-pyinstrument profiling-pyspy ## Profiling of the Glances software @@ -167,12 +156,12 @@ memory-profiling: ## Profile memory usage @echo "It's a very long test (~4 hours)..." rm -f $(PROFILE) @echo "1/2 - Start memory profiling with the history option enable" - $(venv_dev)/mprof run -T 1 -C run-venv.py -C $(CONF) --stop-after $(TIMES) --quiet - $(venv_dev)/mprof plot --output $(OUT_DIR)/glances-memory-profiling-with-history.png + $(venv_full)/mprof run -T 1 -C run-venv.py -C $(CONF) --stop-after $(TIMES) --quiet + $(venv_full)/mprof plot --output $(OUT_DIR)/glances-memory-profiling-with-history.png rm -f $(PROFILE) @echo "2/2 - Start memory profiling with the history option disable" - $(venv_dev)/mprof run -T 1 -C run-venv.py -C $(CONF) --disable-history --stop-after $(TIMES) --quiet - $(venv_dev)/mprof plot --output $(OUT_DIR)/glances-memory-profiling-without-history.png + $(venv_full)/mprof run -T 1 -C run-venv.py -C $(CONF) --disable-history --stop-after $(TIMES) --quiet + $(venv_full)/mprof plot --output $(OUT_DIR)/glances-memory-profiling-without-history.png rm -f $(PROFILE) # Trivy installation: https://aquasecurity.github.io/trivy/latest/getting-started/installation/ @@ -220,7 +209,7 @@ webui-audit-fix: ## Fix audit the Web UI # Packaging # =================================================================== -flatpak: venv-dev-upgrade ## Generate FlatPack JSON file +flatpak: venv-upgrade ## Generate FlatPack JSON file git clone https://github.com/flatpak/flatpak-builder-tools.git $(PYTHON) ./flatpak-builder-tools/pip/flatpak-pip-generator glances rm -rf ./flatpak-builder-tools diff --git a/dev-requirements.txt b/dev-requirements.txt index b0ade583..df0ee950 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -8,6 +8,7 @@ pillow>=10.0.1 # not directly required, pinned by Snyk to avoid a vulnerability pre-commit py-spy pyright +pytest requirements-parser ruff semgrep diff --git a/glances/main.py b/glances/main.py index bbd8a439..8a29fd72 100644 --- a/glances/main.py +++ b/glances/main.py @@ -96,10 +96,68 @@ Examples of use: """ - def __init__(self): + def __init__(self, args_begin_at=1): """Manage the command line arguments.""" - # Read the command line arguments - self.args = self.parse_args() + self.init_glances(args_begin_at) + + def init_glances(self, args_begin_at): + """Main method to init Glances.""" + # Read the command line arguments or parse the one given in parameter (parser) + self.args = self.parse_args(args_begin_at) + + # Load the configuration file, if it exists + # This function should be called after the parse_args + # because the configuration file path can be defined + self.config = Config(self.args.conf_file) + + # Init Glances debug mode + self.init_debug(self.args) + + # Plugins Glances refresh rate + self.init_refresh_rate(self.args) + + # Manage Plugins disable/enable option + self.init_plugins(self.args) + + # Init Glances client/server mode + self.init_client_server(self.args) + + # Init UI mode + self.init_ui_mode(self.args) + + # Init the generate_graph tag + # Should be set to True to generate graphs + self.args.generate_graph = False + + # Export is only available in standalone or client mode (issue #614) + export_tag = self.args.export is not None and any(self.args.export) + if WINDOWS and export_tag: + # On Windows, export is possible but only in quiet mode + # See issue #1038 + logger.info("On Windows OS, export disable the Web interface") + self.args.quiet = True + self.args.webserver = False + elif not (self.is_standalone() or self.is_client()) and export_tag: + logger.critical("Export is only available in standalone or client mode") + sys.exit(2) + + # Filter is only available in standalone mode + if not self.args.process_filter and not self.is_standalone(): + logger.debug("Process filter is only available in standalone mode") + + # Cursor option is only available in standalone mode + if not self.args.disable_cursor and not self.is_standalone(): + logger.debug("Cursor is only available in standalone mode") + + # Let the plugins known the Glances mode + self.args.is_standalone = self.is_standalone() + self.args.is_client = self.is_client() + self.args.is_client_browser = self.is_client_browser() + self.args.is_server = self.is_server() + self.args.is_webserver = self.is_webserver() + + # Check mode compatibility + self.check_mode_compatibility() def version_msg(self): """Return the version message.""" @@ -728,68 +786,11 @@ Examples of use: if args.disable_unicode: args.enable_separator = False - def parse_args(self): - """Parse command line arguments.""" - args = self.init_args().parse_args() - - # Load the configuration file, if it exists - # This function should be called after the parse_args - # because the configuration file path can be defined - self.config = Config(args.conf_file) - - # Init Glances debug mode - self.init_debug(args) - - # Plugins Glances refresh rate - self.init_refresh_rate(args) - - # Manage Plugins disable/enable option - self.init_plugins(args) - - # Init Glances client/server mode - self.init_client_server(args) - - # Init UI mode - self.init_ui_mode(args) - - # Init the generate_graph tag - # Should be set to True to generate graphs - args.generate_graph = False - - # Control parameter and exit if it is not OK - self.args = args - - # Export is only available in standalone or client mode (issue #614) - export_tag = self.args.export is not None and any(self.args.export) - if WINDOWS and export_tag: - # On Windows, export is possible but only in quiet mode - # See issue #1038 - logger.info("On Windows OS, export disable the Web interface") - self.args.quiet = True - self.args.webserver = False - elif not (self.is_standalone() or self.is_client()) and export_tag: - logger.critical("Export is only available in standalone or client mode") - sys.exit(2) - - # Filter is only available in standalone mode - if not args.process_filter and not self.is_standalone(): - logger.debug("Process filter is only available in standalone mode") - - # Cursor option is only available in standalone mode - if not args.disable_cursor and not self.is_standalone(): - logger.debug("Cursor is only available in standalone mode") - - # Let the plugins known the Glances mode - self.args.is_standalone = self.is_standalone() - self.args.is_client = self.is_client() - self.args.is_client_browser = self.is_client_browser() - self.args.is_server = self.is_server() - self.args.is_webserver = self.is_webserver() - - # Check mode compatibility - self.check_mode_compatibility() - - return args + def parse_args(self, args_begin_at): + """Parse command line arguments. + Glances args start at position args_begin_at. + """ + return self.init_args().parse_args(sys.argv[args_begin_at:]) def check_mode_compatibility(self): """Check mode compatibility""" diff --git a/glances/plugins/gpu/__init__.py b/glances/plugins/gpu/__init__.py index fd1d8e43..ff489857 100644 --- a/glances/plugins/gpu/__init__.py +++ b/glances/plugins/gpu/__init__.py @@ -77,7 +77,7 @@ class PluginModel(GlancesPluginModel): self.nvidia = NvidiaGPU() self.amd = AmdGPU() # Just for test purpose (uncomment to test on computer without AMD GPU) - # self.amd = AmdGPU(drm_root_folder='./test-data/plugins/gpu/amd/sys/class/drm') + # self.amd = AmdGPU(drm_root_folder='./tests-data/plugins/gpu/amd/sys/class/drm') # We want to display the stat in the curse interface self.display_curse = True diff --git a/glances/plugins/gpu/cards/amd.py b/glances/plugins/gpu/cards/amd.py index e00b955b..259f10f9 100644 --- a/glances/plugins/gpu/cards/amd.py +++ b/glances/plugins/gpu/cards/amd.py @@ -14,7 +14,7 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually """ # Example -# test-data/plugins/gpu/amd/ +# tests-data/plugins/gpu/amd/ # └── sys # ├── class # │   └── drm diff --git a/pyproject.toml b/pyproject.toml index 5b321a49..ded2515b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -191,7 +191,7 @@ exclude = [ "venv-dev", "venv-min", "docs", - "test-data", + "tests-data", "./glances/outputs/static/*", ] diff --git a/test-data/issues/issue2849.py b/tests-data/issues/issue2849.py similarity index 100% rename from test-data/issues/issue2849.py rename to tests-data/issues/issue2849.py diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/gpu_busy_percent b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/gpu_busy_percent similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/gpu_busy_percent rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/gpu_busy_percent diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_total b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_total similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_total rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_total diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_used b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_used similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_used rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/mem_info_vram_used diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_mclk b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_mclk similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_mclk rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_mclk diff --git a/test-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_sclk b/tests-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_sclk similarity index 100% rename from test-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_sclk rename to tests-data/plugins/gpu/amd/sys/class/drm/card0/device/pp_dpm_sclk diff --git a/test-data/plugins/gpu/amd/sys/kernel/debug/dri/0/amdgpu_pm_info b/tests-data/plugins/gpu/amd/sys/kernel/debug/dri/0/amdgpu_pm_info similarity index 100% rename from test-data/plugins/gpu/amd/sys/kernel/debug/dri/0/amdgpu_pm_info rename to tests-data/plugins/gpu/amd/sys/kernel/debug/dri/0/amdgpu_pm_info diff --git a/unittest-core.py b/unittest-core.py index 6c796b95..69776352 100755 --- a/unittest-core.py +++ b/unittest-core.py @@ -35,7 +35,7 @@ from glances.thresholds import ( # ================= # Init Glances core -core = GlancesMain() +core = GlancesMain(args_begin_at=2) test_config = core.get_config() test_args = core.get_args()