diff --git a/modules/ts/misc/xls-report.py b/modules/ts/misc/xls-report.py index 4e2d8c63b2..24891ff7c0 100755 --- a/modules/ts/misc/xls-report.py +++ b/modules/ts/misc/xls-report.py @@ -40,9 +40,15 @@ 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 - of the configuration the XML file corresponds to. Otherwise, a warning is - printed. A warning is also printed if two different property sets match to the - same configuration name. + of the configuration the XML file corresponds to. A warning is printed if + two different property sets match to the 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] List of names for compile-time and runtime configurations of OpenCV. @@ -97,18 +103,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') class Collector(object): - def __init__(self, config_match_func): + def __init__(self, config_match_func, include_unmatched): self.__config_cache = {} self.config_match_func = config_match_func + self.include_unmatched = include_unmatched self.tests = {} + self.extra_configurations = set() # 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. @staticmethod - def __format_config_cache_key(pairs): - return '{' + ', '.join(repr(k) + ': ' + repr(v) for (k, v) in pairs) + '}' + def __format_config_cache_key(pairs, multiline=False): + 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) module = run.properties['module_name'] @@ -124,8 +137,17 @@ class Collector(object): configuration = self.config_match_func(properties) if configuration is None: - logging.warning('failed to match properties to a configuration: %s', - Collector.__format_config_cache_key(props_key)) + if self.include_unmatched: + 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: same_config_props = [it[0] for it in self.__config_cache.iteritems() if it[1] == configuration] if len(same_config_props) > 0: @@ -160,6 +182,8 @@ def main(): 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('-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() @@ -187,12 +211,18 @@ def main(): config_names = sheet_conf.get('configurations', []) 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): logging.info('looking in %s', root) 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))))