From 7adced41c4e34d300d8bfae04471e792eedefa69 Mon Sep 17 00:00:00 2001 From: JWM Date: Wed, 4 Sep 2024 15:48:42 +0200 Subject: [PATCH 01/16] Move logging from conf.py to setup(app); Default WARNING level --- example/conf.py | 11 +---------- mlx/coverity/coverity.py | 12 +++++++++++- mlx/coverity/coverity_logging.py | 2 -- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/example/conf.py b/example/conf.py index 2835704..a29470d 100644 --- a/example/conf.py +++ b/example/conf.py @@ -15,10 +15,9 @@ import sys import mlx.coverity -from mlx.coverity import __version__, coverity_logging +from mlx.coverity import __version__ import mlx.traceability from decouple import config -import logging pkg_version = __version__ @@ -320,11 +319,3 @@ TRACEABILITY_ITEM_ID_REGEX = r"([A-Z_]+-[A-Z0-9_]+)" TRACEABILITY_ITEM_RELINK = {} -log_level = os.environ.get('LOGLEVEL', None) -if log_level: - try: - numeric_level = getattr(logging, log_level.upper(), None) - coverity_logging.LOGGER.setLevel(level=numeric_level) - except: - raise ValueError(f"Invalid log level: {log_level}") - diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index c33f42d..e60ef5b 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -8,12 +8,15 @@ """ from getpass import getpass +import logging +import os +from sphinx.util.logging import getLogger from urllib.error import URLError, HTTPError from docutils import nodes from .__coverity_version__ import __version__ -from .coverity_logging import report_info, report_warning +from .coverity_logging import report_info, report_warning, LOGGER from .coverity_services import CoverityDefectService from .coverity_directives.coverity_defect_list import ( CoverityDefect, @@ -159,6 +162,13 @@ def get_filtered_defects(self, node): # Extension setup def setup(app): """Extension setup""" + log_level = os.environ.get('LOGLEVEL', "WARNING") + try: + numeric_level = getattr(logging, log_level.upper()) + LOGGER.setLevel(numeric_level) + except: + raise ValueError(f"Invalid log level: {log_level}") + # Create default configuration. Can be customized in conf.py app.add_config_value( "coverity_credentials", diff --git a/mlx/coverity/coverity_logging.py b/mlx/coverity/coverity_logging.py index 31e67e9..070667a 100644 --- a/mlx/coverity/coverity_logging.py +++ b/mlx/coverity/coverity_logging.py @@ -1,10 +1,8 @@ """Module to provide functions that accommodate logging.""" from sphinx.util.logging import getLogger -from logging import WARNING LOGGER = getLogger(__name__) -LOGGER.setLevel(WARNING) def report_warning(msg, docname, lineno=None): From 63d370f96064214fdd82cb087c7cafd21afcce83 Mon Sep 17 00:00:00 2001 From: JWM Date: Wed, 4 Sep 2024 15:56:08 +0200 Subject: [PATCH 02/16] Delete unused import --- mlx/coverity/coverity.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index e60ef5b..f356400 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -10,7 +10,6 @@ from getpass import getpass import logging import os -from sphinx.util.logging import getLogger from urllib.error import URLError, HTTPError from docutils import nodes From 0c606ff53994a0c0c98b62cdc5375365aa9dce41 Mon Sep 17 00:00:00 2001 From: JWM Date: Wed, 4 Sep 2024 15:59:11 +0200 Subject: [PATCH 03/16] Don't use bare except --- mlx/coverity/coverity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index f356400..55479ef 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -165,8 +165,8 @@ def setup(app): try: numeric_level = getattr(logging, log_level.upper()) LOGGER.setLevel(numeric_level) - except: - raise ValueError(f"Invalid log level: {log_level}") + except AttributeError: + raise ValueError(f"Invalid LOGLEVEL: {log_level}") # Create default configuration. Can be customized in conf.py app.add_config_value( From b48a604de124208386a37f53b7404a1af8faac99 Mon Sep 17 00:00:00 2001 From: JWM Date: Thu, 5 Sep 2024 10:48:04 +0200 Subject: [PATCH 04/16] Snapshot defaults to empty string for backwards compatibility --- mlx/coverity/coverity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 55479ef..88656e2 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -48,7 +48,7 @@ def initialize_environment(self, app): \\makeatother""" self.stream = app.config.coverity_credentials["stream"] - self.snapshot = app.config.coverity_credentials["snapshot"] + self.snapshot = app.config.coverity_credentials.get("snapshot", "") # Login to Coverity and obtain stream information try: self.input_credentials(app.config.coverity_credentials) From 656ce7efc0ace65f79edd597a85039b73d617eee Mon Sep 17 00:00:00 2001 From: JWM Date: Thu, 5 Sep 2024 17:15:28 +0200 Subject: [PATCH 05/16] Validate coverity_credentials to give proper error --- mlx/coverity/coverity.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 5c5f29b..1605dc2 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -158,6 +158,15 @@ def get_filtered_defects(self, node): report_info("%d received" % (defects["totalRows"])) return defects +def validate_coverity_credentials(app): + """Validate the configuration of coverity_credentials. + + Args: + app (sphinx.application.Sphinx): Sphinx' application object. + """ + for required_element in ["hostname", "username", "password", "stream"]: + if required_element not in app.config.coverity_credentials: + LOGGER.error(f"{required_element} is a required configuration in 'coverity_credentials' in conf.py") # Extension setup def setup(app): @@ -172,15 +181,13 @@ def setup(app): # Create default configuration. Can be customized in conf.py app.add_config_value( "coverity_credentials", - { - "hostname": "scan.coverity.com", - "username": "reporter", - "password": "coverity", - "stream": "some_stream", - }, + {}, "env", + dict, ) + validate_coverity_credentials(app) + app.add_config_value("TRACEABILITY_ITEM_ID_REGEX", r"([A-Z_]+-[A-Z0-9_]+)", "env") app.add_config_value("TRACEABILITY_ITEM_RELINK", {}, "env") From c2da0933b2772d9f8ebf2bc51adfaf96a31c6a44 Mon Sep 17 00:00:00 2001 From: JWM Date: Fri, 6 Sep 2024 11:20:22 +0200 Subject: [PATCH 06/16] Refactor logging; delete coverity_logging and use Sphinx logging with verbosity level --- example/Makefile | 2 - mlx/coverity/__init__.py | 3 - mlx/coverity/coverity.py | 62 ++++++++++--------- .../coverity_defect_list.py | 11 ++-- mlx/coverity/coverity_item_element.py | 9 ++- mlx/coverity/coverity_logging.py | 29 --------- mlx/coverity/coverity_services.py | 26 ++++---- 7 files changed, 58 insertions(+), 84 deletions(-) delete mode 100644 mlx/coverity/coverity_logging.py diff --git a/example/Makefile b/example/Makefile index 6cc49ad..e7cf00e 100644 --- a/example/Makefile +++ b/example/Makefile @@ -10,7 +10,6 @@ BUILDDIR ?= _build # logging variables DEBUG ?= 0 -LOGLEVEL ?= WARNING # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 @@ -50,7 +49,6 @@ clean: -rm -rf $(BUILDDIR)/* html: - export LOGLEVEL=$(LOGLEVEL) $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/mlx/coverity/__init__.py b/mlx/coverity/__init__.py index d9fa3e3..caf5b07 100644 --- a/mlx/coverity/__init__.py +++ b/mlx/coverity/__init__.py @@ -5,13 +5,10 @@ "CoverityDefectListDirective", "CoverityDefectService", "ItemElement", - "report_info", - "report_warning", "SphinxCoverityConnector", ] from .__coverity_version__ import __version__ -from .coverity_logging import report_info, report_warning from .coverity import SphinxCoverityConnector from .coverity_services import CoverityDefectService from .coverity_item_element import ItemElement diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 1605dc2..b715282 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -11,17 +11,19 @@ import logging import os from urllib.error import URLError, HTTPError +from sphinx.util.logging import getLogger, VERBOSITY_MAP from docutils import nodes from .__coverity_version__ import __version__ -from .coverity_logging import report_info, report_warning, LOGGER from .coverity_services import CoverityDefectService from .coverity_directives.coverity_defect_list import ( CoverityDefect, CoverityDefectListDirective, ) +LOGGER = getLogger("mlx.coverity") + class SphinxCoverityConnector: """ @@ -52,35 +54,35 @@ def initialize_environment(self, app): # Login to Coverity and obtain stream information try: self.input_credentials(app.config.coverity_credentials) - report_info("Initialize a session on Coverity server... ", True) + LOGGER.info("Initialize a session on Coverity server... ") self.coverity_service = CoverityDefectService( app.config.coverity_credentials["hostname"], ) self.coverity_service.login( app.config.coverity_credentials["username"], app.config.coverity_credentials["password"] ) - report_info("done") - report_info("Verify the given stream name... ") + LOGGER.info("done") + LOGGER.info("Verify the given stream name... ") self.coverity_service.validate_stream(self.stream) - report_info("done") + LOGGER.info("done") if self.snapshot: - report_info("Verify the given snapshot ID and obtain all enabled checkers... ") + LOGGER.info("Verify the given snapshot ID and obtain all enabled checkers... ") self.coverity_service.validate_snapshot(self.snapshot) - report_info("done") + LOGGER.info("done") # Get all column keys - report_info("obtaining all column keys... ") + LOGGER.info("obtaining all column keys... ") self.coverity_service.retrieve_column_keys() - report_info("done") + LOGGER.info("done") # Get all checkers - report_info("obtaining all checkers... ") + LOGGER.info("obtaining all checkers... ") self.coverity_service.retrieve_checkers() - report_info("done") + LOGGER.info("done") except (URLError, HTTPError, Exception, ValueError) as error_info: # pylint: disable=broad-except if isinstance(error_info, EOFError): self.coverity_login_error_msg = "Coverity credentials are not configured." else: self.coverity_login_error_msg = str(error_info) - report_info("failed with: %s" % error_info) + LOGGER.info(f"failed with: {error_info}") self.coverity_login_error = True # ----------------------------------------------------------------------------- @@ -96,7 +98,7 @@ def process_coverity_nodes(self, app, doctree, fromdocname): for node in doctree.traverse(CoverityDefect): top_node = node.create_top_node("Failed to connect to Coverity Server") node.replace_self(top_node) - report_warning("Connection failed: %s" % self.coverity_login_error_msg, fromdocname) + LOGGER.warning(f"Connection failed: {self.coverity_login_error_msg}", location=fromdocname) return # Item matrix: @@ -106,20 +108,22 @@ def process_coverity_nodes(self, app, doctree, fromdocname): # Get items from server try: defects = self.get_filtered_defects(node) - if defects["totalRows"] == -1: - error_message = "There are no defects with the specified filters" - report_warning(error_message, fromdocname, lineno=node["line"]) - else: - report_info("building defects table and/or chart... ", True) - node.perform_replacement(defects, self, app, fromdocname) - report_info("done") - except (URLError, AttributeError, Exception) as err: # pylint: disable=broad-except + except URLError as err: error_message = f"failed to process coverity-list with {err!r}" - report_warning(error_message, fromdocname, lineno=node["line"]) + LOGGER.warning(error_message, location=(fromdocname, node["line"])) top_node = node.create_top_node(node["title"]) top_node += nodes.paragraph(text=error_message) node.replace_self(top_node) continue + else: + if defects["totalRows"] == -1: + error_message = "There are no defects with the specified filters" + LOGGER.warning(error_message, location=(fromdocname, node["line"])) + else: + LOGGER.info("building defects table and/or chart... ") + node.perform_replacement(defects, self, app, fromdocname) + LOGGER.info("done") + # ----------------------------------------------------------------------------- # Helper functions of event handlers @@ -150,12 +154,12 @@ def get_filtered_defects(self, node): "rows": [list of dictionaries {"key": , "value": }] } """ - report_info("obtaining defects... ") + LOGGER.info("obtaining defects... ") column_names = set(node["col"]) if "chart_attribute" in node and node["chart_attribute"].upper() in node.column_map: column_names.add(node["chart_attribute"]) defects = self.coverity_service.get_defects(self.stream, node["filters"], column_names, self.snapshot) - report_info("%d received" % (defects["totalRows"])) + LOGGER.info("%d received" % (defects["totalRows"])) return defects def validate_coverity_credentials(app): @@ -171,12 +175,10 @@ def validate_coverity_credentials(app): # Extension setup def setup(app): """Extension setup""" - log_level = os.environ.get('LOGLEVEL', "WARNING") - try: - numeric_level = getattr(logging, log_level.upper()) - LOGGER.setLevel(numeric_level) - except AttributeError: - raise ValueError(f"Invalid LOGLEVEL: {log_level}") + + # Set logging level with --verbose (-v) option of Sphinx, + # This option can be given up to three times to get more debug logging output. + LOGGER.setLevel(VERBOSITY_MAP[app.verbosity]) # Create default configuration. Can be customized in conf.py app.add_config_value( diff --git a/mlx/coverity/coverity_directives/coverity_defect_list.py b/mlx/coverity/coverity_directives/coverity_defect_list.py index 74f01b7..4629aad 100644 --- a/mlx/coverity/coverity_directives/coverity_defect_list.py +++ b/mlx/coverity/coverity_directives/coverity_defect_list.py @@ -3,6 +3,7 @@ from hashlib import sha256 from os import environ, path from pathlib import Path +from sphinx.util.logging import getLogger from docutils import nodes from docutils.parsers.rst import Directive, directives @@ -12,9 +13,9 @@ mpl.use("Agg") import matplotlib.pyplot as plt -from ..coverity_logging import report_info, report_warning from ..coverity_item_element import ItemElement +LOGGER = getLogger("mlx.coverity") def pct_wrapper(sizes): """Helper function for matplotlib which returns the percentage and the absolute size of the slice. @@ -88,7 +89,7 @@ def perform_replacement(self, defects, connector, app, fromdocname): try: self.fill_table_and_count_attributes(defects["rows"], self.coverity_service.columns, app, fromdocname) except AttributeError as err: - report_info("No issues matching your query or empty stream. %s" % err) + LOGGER.info(f"No issues matching your query or empty stream. {err}") top_node += nodes.paragraph(text="No issues matching your query or empty stream") # don't generate empty pie chart image self.replace_self(top_node) @@ -150,9 +151,9 @@ def initialize_labels(self, labels, docname): attr_values = label.split("+") for attr_val in attr_values: if attr_val in self.chart_labels: - report_warning( - "Attribute value '%s' should be unique in chart option." % attr_val, - docname, + LOGGER.warning( + f"Attribute value {attr_val!r} should be unique in chart option.", + location=docname, ) self.chart_labels[attr_val] = 0 if len(attr_values) > 1: diff --git a/mlx/coverity/coverity_item_element.py b/mlx/coverity/coverity_item_element.py index 314c8a1..5cc7361 100644 --- a/mlx/coverity/coverity_item_element.py +++ b/mlx/coverity/coverity_item_element.py @@ -5,8 +5,10 @@ from docutils import nodes from sphinx.errors import NoUri from urlextract import URLExtract +from sphinx.util.logging import getLogger -from .coverity_logging import report_warning + +LOGGER = getLogger("mlx.coverity") class ItemElement(nodes.General, nodes.Element): @@ -197,7 +199,10 @@ def make_internal_item_ref(app, fromdocname, item_id, cid): return None item_info = env.traceability_collection.get_item(item_id) if not item_info: - report_warning("CID %s: Could not find item ID '%s' in traceability collection." % (cid, item_id), fromdocname) + LOGGER.warning( + f"CID {cid}: Could not find item ID {item_id!r} in traceability collection.", + location=fromdocname + ) return None ref_node = nodes.reference("", "") ref_node["refdocname"] = item_info.docname diff --git a/mlx/coverity/coverity_logging.py b/mlx/coverity/coverity_logging.py deleted file mode 100644 index 070667a..0000000 --- a/mlx/coverity/coverity_logging.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Module to provide functions that accommodate logging.""" - -from sphinx.util.logging import getLogger - -LOGGER = getLogger(__name__) - - -def report_warning(msg, docname, lineno=None): - """Convenience function for logging a warning - - Args: - msg (str): Message of the warning - docname (str): Name of the document in which the error occurred - lineno (str): Line number in the document on which the error occurred - """ - if lineno is not None: - LOGGER.warning(msg, location=(docname, lineno)) - else: - LOGGER.warning(msg, location=docname) - - -def report_info(msg, nonl=False): - """Convenience function for information printing - - Args: - msg (str): Message of the warning - nonl (bool): True when no new line at end - """ - LOGGER.info(msg, nonl=nonl) diff --git a/mlx/coverity/coverity_services.py b/mlx/coverity/coverity_services.py index 6b580a6..2757915 100644 --- a/mlx/coverity/coverity_services.py +++ b/mlx/coverity/coverity_services.py @@ -9,7 +9,8 @@ import requests from sphinx.util.logging import getLogger -from mlx.coverity import report_info, report_warning + +LOGGER = getLogger("mlx.coverity") # Coverity built in Impact statuses IMPACT_LIST = ["High", "Medium", "Low"] @@ -52,7 +53,6 @@ def __init__(self, hostname): self._api_endpoint = f"https://{hostname}/api/{self.version}" self._checkers = [] self._columns = {} - self.logger = getLogger("mlx.coverity_logging") self.valid_snapshot = False @property @@ -103,7 +103,7 @@ def column_keys(self, column_names): elif column_name_lower in self.columns: column_keys.add(self.columns[column_name_lower]) else: - self.logger.warning(f"Invalid column name {column_name!r}") + LOGGER.warning(f"Invalid column name {column_name!r}") return column_keys def login(self, username, password): @@ -138,9 +138,9 @@ def validate_snapshot(self, snapshot): response = self.session.get(url) if response.ok: self.valid_snapshot = True - report_info(f"Snapshot ID {snapshot} is valid") + LOGGER.info(f"Snapshot ID {snapshot} is valid") else: - report_warning(f"No snapshot found for ID {snapshot}; Continue with using the latest snapshot.", "") + LOGGER.warning(f"No snapshot found for ID {snapshot}; Continue with using the latest snapshot.") self.valid_snapshot = False def retrieve_issues(self, filters): @@ -218,7 +218,7 @@ def _request(self, url, data=None): err_msg = response.json()["message"] except (requests.exceptions.JSONDecodeError, KeyError): err_msg = response.content.decode() - self.logger.error(err_msg) + LOGGER.error(err_msg) return response.raise_for_status() def assemble_query_filter(self, column_name, filter_values, matcher_type): @@ -246,7 +246,7 @@ def assemble_query_filter(self, column_name, filter_values, matcher_type): matchers.append(matcher) if column_name not in self.columns: - self.logger.warning(f"Invalid column name {column_name!r}; Retrieve column keys first.") + LOGGER.warning(f"Invalid column name {column_name!r}; Retrieve column keys first.") return { "columnKey": self.columns[column_name], @@ -277,7 +277,7 @@ def get_defects(self, stream, filters, column_names, snapshot): "rows": list of [list of dictionaries {"key": , "value": }] } """ - report_info(f"Querying Coverity for defects in stream [{stream}] ...") + LOGGER.info(f"Querying Coverity for defects in stream [{stream}] ...") query_filters = [ { "columnKey": "streams", @@ -326,7 +326,7 @@ def get_defects(self, stream, filters, column_names, snapshot): } defects_data = self.retrieve_issues(data) - report_info("done") + LOGGER.info("done") return defects_data @@ -343,11 +343,11 @@ def handle_attribute_filter(self, attribute_values, name, valid_attributes, allo Returns: set[str]: The attributes values to query with """ - report_info(f"Using {name!r} filter [{attribute_values}]") + LOGGER.info(f"Using {name!r} filter [{attribute_values}]") filter_values = set() for field in attribute_values.split(","): if not valid_attributes or field in valid_attributes: - report_info(f"Classification [{field}] is valid") + LOGGER.info(f"Classification [{field}] is valid") filter_values.add(field) elif allow_regex: pattern = re.compile(field) @@ -355,7 +355,7 @@ def handle_attribute_filter(self, attribute_values, name, valid_attributes, allo if pattern.search(element): filter_values.add(element) else: - self.logger.error(f"Invalid {name} filter: {field}") + LOGGER.error(f"Invalid {name} filter: {field}") return filter_values def handle_component_filter(self, attribute_values): @@ -367,7 +367,7 @@ def handle_component_filter(self, attribute_values): Returns: list[str]: The list of attributes """ - report_info(f"Using 'Component' filter [{attribute_values}]") + LOGGER.info(f"Using 'Component' filter [{attribute_values}]") parser = csv.reader([attribute_values]) filter_values = [] for fields in parser: From b7fa6f1f4c81615fb9341ea377932ddae5ae1b6d Mon Sep 17 00:00:00 2001 From: JWM Date: Fri, 6 Sep 2024 11:21:06 +0200 Subject: [PATCH 07/16] Add info about the new argument snapshot in README --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index c31b92f..0f8a6e5 100644 --- a/README.rst +++ b/README.rst @@ -95,8 +95,11 @@ Example of custom credentials for the plugin: 'username': 'reporter', 'password': 'coverity', 'stream': 'some_coverity_stream', + 'snapshot': '1', } +Snapshot is optional. When an empty string is given, the last snapshot is used. + Link to traceability items ========================== From 037db051c30f833b3c412305703d3e468c97bdba Mon Sep 17 00:00:00 2001 From: Jasper Craeghs <28319872+JasperCraeghs@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:07:21 +0200 Subject: [PATCH 08/16] Improve wording of warning --- mlx/coverity/coverity_services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlx/coverity/coverity_services.py b/mlx/coverity/coverity_services.py index 3e8dfeb..d3d3941 100644 --- a/mlx/coverity/coverity_services.py +++ b/mlx/coverity/coverity_services.py @@ -139,7 +139,7 @@ def validate_snapshot(self, snapshot): LOGGER.info(f"Snapshot ID {snapshot} is valid") valid_snapshot = snapshot else: - LOGGER.warning(f"No snapshot found for ID {snapshot}; Continue with using the latest snapshot.") + LOGGER.warning(f"No snapshot found for ID {snapshot}, using the latest snapshot instead") valid_snapshot = "last()" return valid_snapshot From 9e0cde81183d3afc24876f9cab593e73d16e721b Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 13:27:01 +0200 Subject: [PATCH 09/16] Fix flake8 --- mlx/coverity/coverity.py | 5 ++--- mlx/coverity/coverity_directives/coverity_defect_list.py | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 518069e..d75f634 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -8,8 +8,6 @@ """ from getpass import getpass -import logging -import os from urllib.error import URLError, HTTPError from sphinx.util.logging import getLogger, VERBOSITY_MAP @@ -126,7 +124,6 @@ def process_coverity_nodes(self, app, doctree, fromdocname): node.perform_replacement(defects, self, app, fromdocname) LOGGER.info("done") - # ----------------------------------------------------------------------------- # Helper functions of event handlers @staticmethod @@ -164,6 +161,7 @@ def get_filtered_defects(self, node): LOGGER.info("%d received" % (defects["totalRows"])) return defects + def validate_coverity_credentials(app): """Validate the configuration of coverity_credentials. @@ -174,6 +172,7 @@ def validate_coverity_credentials(app): if required_element not in app.config.coverity_credentials: LOGGER.error(f"{required_element} is a required configuration in 'coverity_credentials' in conf.py") + # Extension setup def setup(app): """Extension setup""" diff --git a/mlx/coverity/coverity_directives/coverity_defect_list.py b/mlx/coverity/coverity_directives/coverity_defect_list.py index 4629aad..5ee6a8a 100644 --- a/mlx/coverity/coverity_directives/coverity_defect_list.py +++ b/mlx/coverity/coverity_directives/coverity_defect_list.py @@ -17,6 +17,7 @@ LOGGER = getLogger("mlx.coverity") + def pct_wrapper(sizes): """Helper function for matplotlib which returns the percentage and the absolute size of the slice. From d0967feb4dcb52fa6aaa2473e6481bf806b4225f Mon Sep 17 00:00:00 2001 From: JWM <62558419+JokeWaumans@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:47:46 +0200 Subject: [PATCH 10/16] Use dict app.config.coverity_credentials instead of entire app Co-authored-by: Jasper Craeghs <28319872+JasperCraeghs@users.noreply.github.com> --- mlx/coverity/coverity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index d75f634..c55cf36 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -162,7 +162,7 @@ def get_filtered_defects(self, node): return defects -def validate_coverity_credentials(app): +def validate_coverity_credentials(config): """Validate the configuration of coverity_credentials. Args: From d7b683103b962e5223416a523090a28482aaebd6 Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 14:50:37 +0200 Subject: [PATCH 11/16] Use config argument --- mlx/coverity/coverity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index c55cf36..2b8fe75 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -169,7 +169,7 @@ def validate_coverity_credentials(config): app (sphinx.application.Sphinx): Sphinx' application object. """ for required_element in ["hostname", "username", "password", "stream"]: - if required_element not in app.config.coverity_credentials: + if required_element not in config: LOGGER.error(f"{required_element} is a required configuration in 'coverity_credentials' in conf.py") @@ -189,7 +189,7 @@ def setup(app): dict, ) - validate_coverity_credentials(app) + validate_coverity_credentials(app.config.coverity_credentials) app.add_config_value("TRACEABILITY_ITEM_ID_REGEX", r"([A-Z_]+-[A-Z0-9_]+)", "env") app.add_config_value("TRACEABILITY_ITEM_RELINK", {}, "env") From ada21e42ed09e281885b3f90437d5c7acd4fc768 Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 15:00:45 +0200 Subject: [PATCH 12/16] Update docstring of validate_coverity_credentials --- mlx/coverity/coverity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 2b8fe75..884e93f 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -166,7 +166,7 @@ def validate_coverity_credentials(config): """Validate the configuration of coverity_credentials. Args: - app (sphinx.application.Sphinx): Sphinx' application object. + config (dict): The configuration `coverity_credentials`. """ for required_element in ["hostname", "username", "password", "stream"]: if required_element not in config: From a43c680ebce09b0b1507ff525b54b982ee1b1566 Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 15:22:36 +0200 Subject: [PATCH 13/16] Update validate_coverity_credentials to use sets with walrus operator and use it in initialize_environment --- mlx/coverity/coverity.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 884e93f..9cc8183 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -22,6 +22,15 @@ LOGGER = getLogger("mlx.coverity") +def validate_coverity_credentials(config): + """Validate the configuration of coverity_credentials. + + Args: + config (dict): The configuration `coverity_credentials`. + """ + if missing := {"hostname", "username", "password", "stream"}.difference(config): + LOGGER.error(f"Missing mandatory keys from configuration variable 'coverity_credentials' in conf.py: {missing}") + class SphinxCoverityConnector: """ @@ -47,6 +56,7 @@ def initialize_environment(self, app): \\let\@noitemerr\\relax \\makeatother""" + validate_coverity_credentials(app.config.coverity_credentials) self.stream = app.config.coverity_credentials["stream"] self.snapshot = app.config.coverity_credentials.get("snapshot", "") # Login to Coverity and obtain stream information @@ -162,17 +172,6 @@ def get_filtered_defects(self, node): return defects -def validate_coverity_credentials(config): - """Validate the configuration of coverity_credentials. - - Args: - config (dict): The configuration `coverity_credentials`. - """ - for required_element in ["hostname", "username", "password", "stream"]: - if required_element not in config: - LOGGER.error(f"{required_element} is a required configuration in 'coverity_credentials' in conf.py") - - # Extension setup def setup(app): """Extension setup""" @@ -189,8 +188,6 @@ def setup(app): dict, ) - validate_coverity_credentials(app.config.coverity_credentials) - app.add_config_value("TRACEABILITY_ITEM_ID_REGEX", r"([A-Z_]+-[A-Z0-9_]+)", "env") app.add_config_value("TRACEABILITY_ITEM_RELINK", {}, "env") From 9301d3b5d18cd7fc3b43c9357082a99ad6ee8123 Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 15:30:46 +0200 Subject: [PATCH 14/16] Add blank line --- mlx/coverity/coverity.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mlx/coverity/coverity.py b/mlx/coverity/coverity.py index 9cc8183..13fd112 100644 --- a/mlx/coverity/coverity.py +++ b/mlx/coverity/coverity.py @@ -22,6 +22,7 @@ LOGGER = getLogger("mlx.coverity") + def validate_coverity_credentials(config): """Validate the configuration of coverity_credentials. From cabc84b8711cdb797d76ae6f50486b1a5b68a80e Mon Sep 17 00:00:00 2001 From: JWM Date: Mon, 9 Sep 2024 16:10:06 +0200 Subject: [PATCH 15/16] Set minimum version of sphinx to 7.3.0 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 1a5c050..8e199c5 100644 --- a/tox.ini +++ b/tox.ini @@ -47,7 +47,7 @@ deps= mlx.warnings >= 0.1.2 mlx.traceability lxml - sphinx + sphinx >= 7.3.0 whitelist_externals = cp rm From 2e0355b448687e6731e15399ec253b1b23ee28c3 Mon Sep 17 00:00:00 2001 From: Jasper Craeghs Date: Mon, 9 Sep 2024 16:45:51 +0200 Subject: [PATCH 16/16] Revert "Set minimum version of sphinx to 7.3.0" This reverts commit cabc84b8711cdb797d76ae6f50486b1a5b68a80e. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 8e199c5..1a5c050 100644 --- a/tox.ini +++ b/tox.ini @@ -47,7 +47,7 @@ deps= mlx.warnings >= 0.1.2 mlx.traceability lxml - sphinx >= 7.3.0 + sphinx whitelist_externals = cp rm