Merge pull request #1091 from SpecLad:xls-updates
This commit is contained in:
commit
dbf02c71b6
@ -40,9 +40,15 @@
|
|||||||
Corollary 2: an empty 'properties' dictionary matches every property set.
|
Corollary 2: an empty 'properties' dictionary matches every property set.
|
||||||
|
|
||||||
3) If a matching matcher is found, its 'name' string is presumed to be the name
|
3) If a matching matcher is found, its 'name' string is presumed to be the name
|
||||||
of the configuration the XML file corresponds to. Otherwise, a warning is
|
of the configuration the XML file corresponds to. A warning is printed if
|
||||||
printed. A warning is also printed if two different property sets match to the
|
two different property sets match to the same configuration name.
|
||||||
same configuration name.
|
|
||||||
|
4) If a such a matcher isn't found, if --include-unmatched was specified, the
|
||||||
|
configuration name is assumed to be the relative path from the sheet's
|
||||||
|
directory to the XML file's containing directory. If the XML file isinstance
|
||||||
|
directly inside the sheet's directory, the configuration name is instead
|
||||||
|
a dump of all its properties. If --include-unmatched wasn't specified,
|
||||||
|
the XML file is ignored and a warning is printed.
|
||||||
|
|
||||||
* 'configurations': [string]
|
* 'configurations': [string]
|
||||||
List of names for compile-time and runtime configurations of OpenCV.
|
List of names for compile-time and runtime configurations of OpenCV.
|
||||||
@ -67,6 +73,7 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
|
import errno
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import logging
|
import logging
|
||||||
import numbers
|
import numbers
|
||||||
@ -74,7 +81,6 @@ import os, os.path
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from collections import OrderedDict
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from itertools import ifilter
|
from itertools import ifilter
|
||||||
|
|
||||||
@ -96,18 +102,25 @@ error_speedup_style = xlwt.easyxf('pattern: pattern solid, fore_color orange')
|
|||||||
header_style = xlwt.easyxf('font: bold true; alignment: horizontal centre, vertical top, wrap True')
|
header_style = xlwt.easyxf('font: bold true; alignment: horizontal centre, vertical top, wrap True')
|
||||||
|
|
||||||
class Collector(object):
|
class Collector(object):
|
||||||
def __init__(self, config_match_func):
|
def __init__(self, config_match_func, include_unmatched):
|
||||||
self.__config_cache = {}
|
self.__config_cache = {}
|
||||||
self.config_match_func = config_match_func
|
self.config_match_func = config_match_func
|
||||||
|
self.include_unmatched = include_unmatched
|
||||||
self.tests = {}
|
self.tests = {}
|
||||||
|
self.extra_configurations = set()
|
||||||
|
|
||||||
# Format a sorted sequence of pairs as if it was a dictionary.
|
# Format a sorted sequence of pairs as if it was a dictionary.
|
||||||
# We can't just use a dictionary instead, since we want to preserve the sorted order of the keys.
|
# We can't just use a dictionary instead, since we want to preserve the sorted order of the keys.
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __format_config_cache_key(pairs):
|
def __format_config_cache_key(pairs, multiline=False):
|
||||||
return '{' + ', '.join(repr(k) + ': ' + repr(v) for (k, v) in pairs) + '}'
|
return (
|
||||||
|
('{\n' if multiline else '{') +
|
||||||
|
(',\n' if multiline else ', ').join(
|
||||||
|
(' ' if multiline else '') + repr(k) + ': ' + repr(v) for (k, v) in pairs) +
|
||||||
|
('\n}\n' if multiline else '}')
|
||||||
|
)
|
||||||
|
|
||||||
def collect_from(self, xml_path):
|
def collect_from(self, xml_path, default_configuration):
|
||||||
run = parseLogFile(xml_path)
|
run = parseLogFile(xml_path)
|
||||||
|
|
||||||
module = run.properties['module_name']
|
module = run.properties['module_name']
|
||||||
@ -123,8 +136,17 @@ class Collector(object):
|
|||||||
configuration = self.config_match_func(properties)
|
configuration = self.config_match_func(properties)
|
||||||
|
|
||||||
if configuration is None:
|
if configuration is None:
|
||||||
logging.warning('failed to match properties to a configuration: %s',
|
if self.include_unmatched:
|
||||||
Collector.__format_config_cache_key(props_key))
|
if default_configuration is not None:
|
||||||
|
configuration = default_configuration
|
||||||
|
else:
|
||||||
|
configuration = Collector.__format_config_cache_key(props_key, multiline=True)
|
||||||
|
|
||||||
|
self.extra_configurations.add(configuration)
|
||||||
|
else:
|
||||||
|
logging.warning('failed to match properties to a configuration: %s',
|
||||||
|
Collector.__format_config_cache_key(props_key))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
same_config_props = [it[0] for it in self.__config_cache.iteritems() if it[1] == configuration]
|
same_config_props = [it[0] for it in self.__config_cache.iteritems() if it[1] == configuration]
|
||||||
if len(same_config_props) > 0:
|
if len(same_config_props) > 0:
|
||||||
@ -137,11 +159,17 @@ class Collector(object):
|
|||||||
|
|
||||||
if configuration is None: return
|
if configuration is None: return
|
||||||
|
|
||||||
module_tests = self.tests.setdefault(module, OrderedDict())
|
module_tests = self.tests.setdefault(module, {})
|
||||||
|
|
||||||
for test in run.tests:
|
for test in run.tests:
|
||||||
test_results = module_tests.setdefault((test.shortName(), test.param()), {})
|
test_results = module_tests.setdefault((test.shortName(), test.param()), {})
|
||||||
test_results[configuration] = test.get("gmean") if test.status == 'run' else test.status
|
new_result = test.get("gmean") if test.status == 'run' else test.status
|
||||||
|
test_results[configuration] = min(
|
||||||
|
test_results.get(configuration), new_result,
|
||||||
|
key=lambda r: (1, r) if isinstance(r, numbers.Number) else
|
||||||
|
(2,) if r is not None else
|
||||||
|
(3,)
|
||||||
|
) # prefer lower result; prefer numbers to errors and errors to nothing
|
||||||
|
|
||||||
def make_match_func(matchers):
|
def make_match_func(matchers):
|
||||||
def match_func(properties):
|
def match_func(properties):
|
||||||
@ -159,6 +187,8 @@ def main():
|
|||||||
arg_parser.add_argument('sheet_dirs', nargs='+', metavar='DIR', help='directory containing perf test logs')
|
arg_parser.add_argument('sheet_dirs', nargs='+', metavar='DIR', help='directory containing perf test logs')
|
||||||
arg_parser.add_argument('-o', '--output', metavar='XLS', default='report.xls', help='name of output file')
|
arg_parser.add_argument('-o', '--output', metavar='XLS', default='report.xls', help='name of output file')
|
||||||
arg_parser.add_argument('-c', '--config', metavar='CONF', help='global configuration file')
|
arg_parser.add_argument('-c', '--config', metavar='CONF', help='global configuration file')
|
||||||
|
arg_parser.add_argument('--include-unmatched', action='store_true',
|
||||||
|
help='include results from XML files that were not recognized by configuration matchers')
|
||||||
|
|
||||||
args = arg_parser.parse_args()
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
@ -176,7 +206,8 @@ def main():
|
|||||||
try:
|
try:
|
||||||
with open(os.path.join(sheet_path, 'sheet.conf')) as sheet_conf_file:
|
with open(os.path.join(sheet_path, 'sheet.conf')) as sheet_conf_file:
|
||||||
sheet_conf = ast.literal_eval(sheet_conf_file.read())
|
sheet_conf = ast.literal_eval(sheet_conf_file.read())
|
||||||
except Exception:
|
except IOError as ioe:
|
||||||
|
if ioe.errno != errno.ENOENT: raise
|
||||||
sheet_conf = {}
|
sheet_conf = {}
|
||||||
logging.debug('no sheet.conf for %s', sheet_path)
|
logging.debug('no sheet.conf for %s', sheet_path)
|
||||||
|
|
||||||
@ -185,12 +216,18 @@ def main():
|
|||||||
config_names = sheet_conf.get('configurations', [])
|
config_names = sheet_conf.get('configurations', [])
|
||||||
config_matchers = sheet_conf.get('configuration_matchers', [])
|
config_matchers = sheet_conf.get('configuration_matchers', [])
|
||||||
|
|
||||||
collector = Collector(make_match_func(config_matchers))
|
collector = Collector(make_match_func(config_matchers), args.include_unmatched)
|
||||||
|
|
||||||
for root, _, filenames in os.walk(sheet_path):
|
for root, _, filenames in os.walk(sheet_path):
|
||||||
logging.info('looking in %s', root)
|
logging.info('looking in %s', root)
|
||||||
for filename in fnmatch.filter(filenames, '*.xml'):
|
for filename in fnmatch.filter(filenames, '*.xml'):
|
||||||
collector.collect_from(os.path.join(root, filename))
|
if os.path.normpath(sheet_path) == os.path.normpath(root):
|
||||||
|
default_conf = None
|
||||||
|
else:
|
||||||
|
default_conf = os.path.relpath(root, sheet_path)
|
||||||
|
collector.collect_from(os.path.join(root, filename), default_conf)
|
||||||
|
|
||||||
|
config_names.extend(sorted(collector.extra_configurations - set(config_names)))
|
||||||
|
|
||||||
sheet = wb.add_sheet(sheet_conf.get('sheet_name', os.path.basename(os.path.abspath(sheet_path))))
|
sheet = wb.add_sheet(sheet_conf.get('sheet_name', os.path.basename(os.path.abspath(sheet_path))))
|
||||||
|
|
||||||
@ -203,7 +240,7 @@ def main():
|
|||||||
sheet_comparisons = sheet_conf.get('comparisons', [])
|
sheet_comparisons = sheet_conf.get('comparisons', [])
|
||||||
|
|
||||||
for i, w in enumerate([2000, 15000, 2500, 2000, 15000]
|
for i, w in enumerate([2000, 15000, 2500, 2000, 15000]
|
||||||
+ (len(config_names) + 1 + len(sheet_comparisons)) * [3000]):
|
+ (len(config_names) + 1 + len(sheet_comparisons)) * [4000]):
|
||||||
sheet.col(i).width = w
|
sheet.col(i).width = w
|
||||||
|
|
||||||
for i, caption in enumerate(['Module', 'Test', 'Image\nsize', 'Data\ntype', 'Parameters']
|
for i, caption in enumerate(['Module', 'Test', 'Image\nsize', 'Data\ntype', 'Parameters']
|
||||||
@ -218,7 +255,7 @@ def main():
|
|||||||
for module, color in module_colors.iteritems()}
|
for module, color in module_colors.iteritems()}
|
||||||
|
|
||||||
for module, tests in sorted(collector.tests.iteritems()):
|
for module, tests in sorted(collector.tests.iteritems()):
|
||||||
for ((test, param), configs) in tests.iteritems():
|
for ((test, param), configs) in sorted(tests.iteritems()):
|
||||||
sheet.write(row, 0, module, module_styles.get(module, xlwt.Style.default_style))
|
sheet.write(row, 0, module, module_styles.get(module, xlwt.Style.default_style))
|
||||||
sheet.write(row, 1, test)
|
sheet.write(row, 1, test)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user