xls-report.py: added an option to include data from unrecognized XMLs
authorRoman Donchenko <roman.donchenko@itseez.com>
Thu, 4 Jul 2013 14:19:33 +0000 (18:19 +0400)
committerRoman Donchenko <roman.donchenko@itseez.com>
Thu, 4 Jul 2013 16:00:59 +0000 (20:00 +0400)
modules/ts/misc/xls-report.py

index 4e2d8c6..24891ff 100755 (executable)
            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 collect_from(self, xml_path):
+    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, 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))))