Skip to content

Commit

Permalink
Merge pull request #26 from melexis/configuration_file
Browse files Browse the repository at this point in the history
Basic config parsing
  • Loading branch information
SteinHeselmans authored Mar 26, 2018
2 parents 507d62f + 114df92 commit 6e7c22e
Show file tree
Hide file tree
Showing 8 changed files with 461 additions and 49 deletions.
74 changes: 62 additions & 12 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,16 @@ The command returns (shell $? variable):
- value 0 when the number of counted warnings is within the supplied minimum and maximum limits: ok,
- number of counted warnings (positive) when the counter number is not within those limit.

-------------------------
---------------------------
Simple Command line options
---------------------------

Plugin has two forms of passing the arguments to checkers. The command line
option which enables checkers and sets minimum and maximum to each checker
individually, or the configuration file option which provides more flexibility
and also traceability as it resides inside repository and provides option to
adjust minimum and maximum per individual checker.

Parse for Sphinx warnings
-------------------------

Expand All @@ -135,17 +144,16 @@ command:
# command line log file
mlx-warnings doc_log.txt --sphinx
# command line command execution
mlx-warnings --command --sphinx <commandforsphinx>
mlx-warnings --sphinx --command <commandforsphinx>
# explicitly as python module for log file
python3 -m mlx.warnings --sphinx doc_log.txt
python -m mlx.warnings --sphinx doc_log.txt
# explicitly as python module
python3 -m mlx.warnings --command --sphinx <commandforsphinx>
python -m mlx.warnings --command --sphinx <commandforsphinx>
python3 -m mlx.warnings --sphinx --command <commandforsphinx>
python -m mlx.warnings --sphinx --command <commandforsphinx>
--------------------------
Parse for Doxygen warnings
--------------------------

Expand All @@ -157,17 +165,16 @@ command:
# command line log file
mlx-warnings doc_log.txt --doxygen
# command line command execution
mlx-warnings --command --doxygen <commandfordoxygen>
mlx-warnings --doxygen --command <commandfordoxygen>
# explicitly as python module for log file
python3 -m mlx.warnings --doxygen doc_log.txt
python -m mlx.warnings --doxygen doc_log.txt
# explicitly as python module
python3 -m mlx.warnings --command --doxygen <commandfordoxygen>
python -m mlx.warnings --command --doxygen <commandfordoxygen>
python3 -m mlx.warnings --doxygen --command <commandfordoxygen>
python -m mlx.warnings --doxygen --command <commandfordoxygen>
------------------------
Parse for JUnit failures
------------------------

Expand All @@ -179,14 +186,57 @@ command:
# command line log file
mlx-warnings junit_output.xml --junit
# command line command execution
mlx-warnings --command --junit <commandforjunit>
mlx-warnings --junit --command <commandforjunit>
# explicitly as python module for log file
python3 -m mlx.warnings --junit junit_output.xml
python -m mlx.warnings --junit junit_output.xml
# explicitly as python module
python3 -m mlx.warnings --command --junit <commandforjunit>
python -m mlx.warnings --command --junit <commandforjunit>
python3 -m mlx.warnings --junit --command <commandforjunit>
python -m mlx.warnings --junit --command <commandforjunit>
----------------------------------
Configuration file to pass options
----------------------------------

Beside command line, you can pass options through the configuration file.
Configuration file is in JSON format with a simple structure.

.. code-block:: json
{
"sphinx":{
"enabled": true,
"min": 0,
"max": 0
},
"doxygen":{
"enabled": false,
"min": 0,
"max": 0
},
"junit":{
"enabled": false,
"min": 0,
"max": 0
}
}
First key is `checkername`, then it contains a boolean value for key `enabled`,
value for minimum number of warnings with key `min` and value for maximum
number of warnings with key `max`. This structure allows simple expansion.

To run the plugin with configuration file you simply pass `--config` flag with
path to configuration file

.. code-block:: bash
# command line log file
mlx-warnings --config pathtoconfig.json junit_output.xml
# command line command execution
mlx-warnings --config patchtoconfig.json --command <commandforjunit>
-------------
Other options
Expand Down
70 changes: 51 additions & 19 deletions src/mlx/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import print_function

import argparse
import json
import os
import pkg_resources
import subprocess
Expand All @@ -17,7 +18,7 @@

class WarningsPlugin:

def __init__(self, sphinx = False, doxygen = False, junit = False, verbose = False):
def __init__(self, sphinx = False, doxygen = False, junit = False, verbose = False, configfile= None):
'''
Function for initializing the parsers
Expand All @@ -29,12 +30,17 @@ def __init__(self, sphinx = False, doxygen = False, junit = False, verbose = Fal
'''
self.checkerList = {}
self.verbose = verbose
if sphinx:
self.activate_checker(SphinxChecker(self.verbose))
if doxygen:
self.activate_checker(DoxyChecker(self.verbose))
if junit:
self.activate_checker(JUnitChecker(self.verbose))
if configfile is not None:
with open(configfile, 'r') as f:
config = json.load(f)
self.config_parser_json(config)
else:
if sphinx:
self.activate_checker(SphinxChecker(self.verbose))
if doxygen:
self.activate_checker(DoxyChecker(self.verbose))
if junit:
self.activate_checker(JUnitChecker(self.verbose))

self.warn_min = 0
self.warn_max = 0
Expand Down Expand Up @@ -148,32 +154,58 @@ def toggle_printout(self, printout):
'''
self.printout = printout

def config_parser_json(self, config):
''' Parsing configuration dict extracted by previously opened json file
Args:
config (dict): json dump of the configuration
'''
self.publicCheckers = [SphinxChecker(), DoxyChecker(), JUnitChecker()]
# activate checker
for checker in self.publicCheckers:
try:
if bool(config[checker.name]['enabled']):
self.activate_checker(checker)
self.get_checker(checker.name).set_maximum(int(config[checker.name]['max']))
self.get_checker(checker.name).set_minimum(int(config[checker.name]['min']))
print("Config parsing for {name} completed".format(name=checker.name))
except KeyError as e:
print("Incomplete config. Missing: {key}".format(key=e))


def warnings_wrapper(args):
parser = argparse.ArgumentParser(prog='mlx-warnings')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-d', '--doxygen', dest='doxygen', action='store_true')
group.add_argument('-s', '--sphinx', dest='sphinx', action='store_true')
group.add_argument('-j', '--junit', dest='junit', action='store_true')
group1 = parser.add_argument_group('Configuration command line options')
group1.add_argument('-d', '--doxygen', dest='doxygen', action='store_true')
group1.add_argument('-s', '--sphinx', dest='sphinx', action='store_true')
group1.add_argument('-j', '--junit', dest='junit', action='store_true')
group1.add_argument('-m', '--maxwarnings', type=int, required=False, default=0,
help='Maximum amount of warnings accepted')
group1.add_argument('--minwarnings', type=int, required=False, default=0,
help='Minimum amount of warnings accepted')
group2 = parser.add_argument_group('Configuration file with options')
group2.add_argument('--config', dest='configfile', action='store', required=False, help='Config file in JSON format provides toggle of checkers and their limits')
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument('--command', dest='command', action='store_true',
help='Treat program arguments as command to execute to obtain data')
parser.add_argument('--ignore-retval', dest='ignore', action='store_true',
help='Ignore return value of the executed command')
parser.add_argument('-m', '--maxwarnings', type=int, required=False, default=0,
help='Maximum amount of warnings accepted')
parser.add_argument('--minwarnings', type=int, required=False, default=0,
help='Minimum amount of warnings accepted')
parser.add_argument('--version', action='version', version='%(prog)s {version}'.format(version=pkg_resources.require('mlx.warnings')[0].version))

parser.add_argument('logfile', nargs='+', help='Logfile (or command) that might contain warnings')
parser.add_argument('flags', nargs=argparse.REMAINDER, help='Possible not-used flags from above are considered as command flags')

args = parser.parse_args(args)

warnings = WarningsPlugin(sphinx=args.sphinx, doxygen=args.doxygen, junit=args.junit, verbose=args.verbose)
warnings.set_maximum(args.maxwarnings)
warnings.set_minimum(args.minwarnings)
# Read config file
if args.configfile is not None:
if args.sphinx or args.doxygen or args.junit or (args.maxwarnings != 0) or (args.minwarnings != 0):
print("Configfile cannot be provided with other arguments")
sys.exit(2)
warnings = WarningsPlugin(configfile=args.configfile)
else:
warnings = WarningsPlugin(sphinx=args.sphinx, doxygen=args.doxygen, junit=args.junit, verbose=args.verbose)
warnings.set_maximum(args.maxwarnings)
warnings.set_minimum(args.minwarnings)

if args.command:
cmd = args.logfile
Expand Down
21 changes: 13 additions & 8 deletions src/mlx/warnings_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import abc
import re
from junitparser import JUnitXml, Failure, Error
from xml.etree.ElementTree import ParseError


DOXYGEN_WARNING_REGEX = r"(?:((?:[/.]|[A-Za-z]).+?):(-?\d+):\s*([Ww]arning|[Ee]rror)|<.+>:-?\d+(?::\s*([Ww]arning|[Ee]rror))?): (.+(?:(?!\s*(?:[Nn]otice|[Ww]arning|[Ee]rror): )[^/<\n][^:\n][^/\n].+)*)|\s*([Nn]otice|[Ww]arning|[Ee]rror): (.+)\n?"
doxy_pattern = re.compile(DOXYGEN_WARNING_REGEX)
Expand Down Expand Up @@ -166,14 +168,17 @@ def check(self, content):
Args:
content (str): The content to parse
'''
result = JUnitXml.fromstring(content.encode('utf-8'))
if self.verbose:
for suite in result:
for testcase in filter(lambda testcase: isinstance(testcase.result, (Failure, Error)), suite):
print('{classname}.{testname}'.format(classname=testcase.classname,
testname=testcase.name))
result.update_statistics()
self.count += result.errors + result.failures
try:
result = JUnitXml.fromstring(content.encode('utf-8'))
if self.verbose:
for suite in result:
for testcase in filter(lambda testcase: isinstance(testcase.result, (Failure, Error)), suite):
print('{classname}.{testname}'.format(classname=testcase.classname,
testname=testcase.name))
result.update_statistics()
self.count += result.errors + result.failures
except ParseError as _:
return



17 changes: 17 additions & 0 deletions tests/config_example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"sphinx":{
"enabled": true,
"min": 0,
"max": 0
},
"doxygen":{
"enabled": false,
"min": 0,
"max": 0
},
"junit":{
"enabled": false,
"min": 0,
"max": 0
}
}
Loading

0 comments on commit 6e7c22e

Please sign in to comment.