Skip to content

Commit

Permalink
Merge pull request #26 from melexis/visualize_chart
Browse files Browse the repository at this point in the history
Visualize pie chart
  • Loading branch information
Letme authored Jun 24, 2019
2 parents 80cb075 + 08e85b1 commit 3637314
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 12 deletions.
65 changes: 54 additions & 11 deletions mlx/coverity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,29 @@
Sphinx extension for restructured text that adds Coverity reporting to documentation.
See README.rst for more details.
'''

from __future__ import print_function
import matplotlib as mpl
import matplotlib.pyplot as plt
import pkg_resources

from docutils.parsers.rst import Directive
from hashlib import sha256
from os import environ, mkdir, path
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.parsers.rst import Directive, directives
from mlx.coverity_services import CoverityConfigurationService, CoverityDefectService
from sphinx import __version__ as sphinx_version
try:
# For Python 3.0 and later
from urllib.error import URLError, HTTPError
except ImportError:
# Fall back to Python 2's urllib2
from urllib2 import URLError, HTTPError
from sphinx import __version__ as sphinx_version
if sphinx_version >= '1.6.0':
from sphinx.util.logging import getLogger

if not environ.get('DISPLAY'):
mpl.use('Agg')


def report_warning(env, msg, docname, lineno=None):
'''Convenience function for logging a warning
Expand Down Expand Up @@ -57,6 +62,18 @@ def report_info(env, msg, nonl=False):
env.info(msg, nonl=nonl)


def pct_wrapper(sizes):
""" Helper function for matplotlib which returns the percentage and the absolute size of the slice.
Args:
sizes (list): List containing the amount of elements per slice.
"""
def make_pct(pct):
absolute = int(round(pct / 100 * sum(sizes)))
return "{:.0f}%\n({:d})".format(pct, absolute)
return make_pct


# -----------------------------------------------------------------------------
# Declare new node types (based on others):
class CoverityDefect(nodes.General, nodes.Element):
Expand Down Expand Up @@ -248,9 +265,9 @@ def process_coverity_nodes(self, app, doctree, fromdocname):

# Initialize dictionary to store counters
if node['chart']:
classification_count = {}
chart_labels = {}
for label in node['chart'].split(','):
classification_count[tuple(label.split('+'))] = 0
chart_labels[tuple(label.split('+'))] = 0

# Get items from server
report_info(env, 'obtaining defects... ', True)
Expand Down Expand Up @@ -306,9 +323,9 @@ def process_coverity_nodes(self, app, doctree, fromdocname):
if node['chart']:
col = cov_attribute_value_to_col(defect, 'Classification')
classification_value = col.children[0].children[0] # get text in paragraph of column
for label in classification_count.keys():
for label in chart_labels.keys():
if classification_value in label:
classification_count[label] += 1
chart_labels[label] += 1

except AttributeError as err:
report_info(env, 'No issues matching your query or empty stream. %s' % err)
Expand All @@ -320,10 +337,36 @@ def process_coverity_nodes(self, app, doctree, fromdocname):
if node['chart']:
total_defects = defects['totalNumberOfRecords']
total_labeled = 0
for count in classification_count.values():
for count in chart_labels.values():
total_labeled += count
classification_count[('other', )] = total_defects - total_labeled
top_node += nodes.paragraph(text=str(classification_count))
chart_labels[('Other', )] = total_defects - total_labeled
# remove items with count value equal to 0
chart_labels = {k: v for k, v in chart_labels.items() if v}

labels = list(chart_labels.keys()) # list of tuples
labels = [' +\n'.join(label) for label in labels]
sizes = chart_labels.values()

fig, axes = plt.subplots()
axes.pie(sizes, labels=labels, autopct=pct_wrapper(sizes), startangle=90)
axes.axis('equal')
folder_name = path.join(env.app.srcdir, '_images')
if not path.exists(folder_name):
mkdir(folder_name)
hash_string = ''
for pie_slice in axes.__dict__['texts']:
hash_string += str(pie_slice)
hash_value = sha256(hash_string.encode()).hexdigest() # create hash value based on chart parameters
rel_file_path = path.join('_images', 'piechart-{}.png'.format(hash_value))
if rel_file_path not in env.images.keys():
fig.savefig(path.join(env.app.srcdir, rel_file_path), format='png')
# store file name in build env
env.images[rel_file_path] = ['_images', path.split(rel_file_path)[-1]]

image_node = nodes.image()
image_node['uri'] = rel_file_path
image_node['candidates'] = '*' # look at uri value for source path, relative to the srcdir folder
top_node += image_node

report_info(env, "done")
node.replace_self(top_node)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
if sys.version_info[0] == 2:
requires = ['Sphinx>=0.6', 'docutils', 'suds', 'setuptools_scm']
else:
requires = ['Sphinx>=0.6', 'docutils', 'suds-py3', 'setuptools_scm']
requires = ['Sphinx>=0.6', 'docutils', 'suds-py3', 'setuptools_scm', 'matplotlib']


setup(
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ deps=
py27: suds
py37: suds-py3
setuptools_scm
matplotlib
mlx.warnings >= 0.1.2
lxml
sphinx1.3: sphinx <= 1.3.9999
Expand Down

0 comments on commit 3637314

Please sign in to comment.