Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Sphinx logging object consistently #79

Merged
merged 21 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7adced4
Move logging from conf.py to setup(app); Default WARNING level
JokeWaumans Sep 4, 2024
63d370f
Delete unused import
JokeWaumans Sep 4, 2024
0c606ff
Don't use bare except
JokeWaumans Sep 4, 2024
b48a604
Snapshot defaults to empty string for backwards compatibility
JokeWaumans Sep 5, 2024
f41052b
Merge branch 'snapshots' into logging
JokeWaumans Sep 5, 2024
84fba56
Merge branch 'snapshots' into logging
JokeWaumans Sep 5, 2024
656ce7e
Validate coverity_credentials to give proper error
JokeWaumans Sep 5, 2024
c2da093
Refactor logging; delete coverity_logging and use Sphinx logging with…
JokeWaumans Sep 6, 2024
b7fa6f1
Add info about the new argument snapshot in README
JokeWaumans Sep 6, 2024
95c7ad5
Merge branch 'snapshots' into logging
JokeWaumans Sep 9, 2024
97a1c23
Merge branch 'snapshots' into logging
JokeWaumans Sep 9, 2024
037db05
Improve wording of warning
JasperCraeghs Sep 9, 2024
9e0cde8
Fix flake8
JokeWaumans Sep 9, 2024
5a209a4
Merge branch 'logging' of github.com:melexis/sphinx-coverity-extensio…
JokeWaumans Sep 9, 2024
d0967fe
Use dict app.config.coverity_credentials instead of entire app
JokeWaumans Sep 9, 2024
d7b6831
Use config argument
JokeWaumans Sep 9, 2024
ada21e4
Update docstring of validate_coverity_credentials
JokeWaumans Sep 9, 2024
a43c680
Update validate_coverity_credentials to use sets with walrus operator…
JokeWaumans Sep 9, 2024
9301d3b
Add blank line
JokeWaumans Sep 9, 2024
cabc84b
Set minimum version of sphinx to 7.3.0
JokeWaumans Sep 9, 2024
2e0355b
Revert "Set minimum version of sphinx to 7.3.0"
JasperCraeghs Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ Example of custom credentials for the plugin:
'username': 'myusername',
'password': 'mypassword',
'stream': 'some_coverity_stream',
'snapshot': '1',
}

Snapshot is optional. When an empty string is given, the last snapshot is used.

Link to traceability items
==========================

Expand Down
2 changes: 0 additions & 2 deletions example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ BUILDDIR ?= _build

# logging variables
DEBUG ?= 0
LOGLEVEL ?= WARNING

# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
Expand Down Expand Up @@ -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."
Expand Down
11 changes: 1 addition & 10 deletions example/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__

Expand Down Expand Up @@ -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}")

3 changes: 0 additions & 3 deletions mlx/coverity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
78 changes: 48 additions & 30 deletions mlx/coverity/coverity.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
"""

from getpass import getpass
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
from .coverity_services import CoverityDefectService
from .coverity_directives.coverity_defect_list import (
CoverityDefect,
CoverityDefectListDirective,
)

LOGGER = getLogger("mlx.coverity")


class SphinxCoverityConnector:
"""
Expand Down Expand Up @@ -50,37 +54,37 @@ 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.snapshot = self.coverity_service.validate_snapshot(self.snapshot)
report_info("done")
LOGGER.info("done")
else:
self.snapshot = "last()"
# 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

# -----------------------------------------------------------------------------
Expand All @@ -96,7 +100,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:
Expand All @@ -106,20 +110,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
Expand Down Expand Up @@ -150,30 +156,42 @@ def get_filtered_defects(self, node):
"rows": [list of dictionaries {"key": <key>, "value": <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):
JokeWaumans marked this conversation as resolved.
Show resolved Hide resolved
"""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")
JasperCraeghs marked this conversation as resolved.
Show resolved Hide resolved

# Extension setup
def setup(app):
"""Extension setup"""

# 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(
"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")

Expand Down
11 changes: 6 additions & 5 deletions mlx/coverity/coverity_directives/coverity_defect_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 7 additions & 2 deletions mlx/coverity/coverity_item_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down
31 changes: 0 additions & 31 deletions mlx/coverity/coverity_logging.py

This file was deleted.

Loading
Loading