1f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com#!/usr/bin/python 2f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com 39fb6c8ac9ce7dd5d3319b4e3affd5f1e051162a2epoger@google.com""" 4f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comCopyright 2013 Google Inc. 5f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com 6f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comUse of this source code is governed by a BSD-style license that can be 7f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comfound in the LICENSE file. 8f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com 9f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comRepackage expected/actual GM results as needed by our HTML rebaseline viewer. 109fb6c8ac9ce7dd5d3319b4e3affd5f1e051162a2epoger@google.com""" 11f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com 12f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com# System-level imports 1331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.orgimport fnmatch 14f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comimport os 15f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comimport re 16f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com 17f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.com# Imports from within Skia 18b144271179aaf82cb1151e9dfd8e866747402594epogerimport fix_pythonpath # must do this first 19f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comimport gm_json 2031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.orgimport imagepairset 2116f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.org 2216f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.org# Keys used to link an image to a particular GM test. 2316f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.org# NOTE: Keep these in sync with static/constants.js 2468a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.orgVALUE__HEADER__SCHEMA_VERSION = 3 2516f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__EXPECTATIONS__BUGS = gm_json.JSONKEY_EXPECTEDRESULTS_BUGS 2616f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__EXPECTATIONS__IGNOREFAILURE = gm_json.JSONKEY_EXPECTEDRESULTS_IGNOREFAILURE 2716f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__EXPECTATIONS__REVIEWED = gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED 2868a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.orgKEY__EXTRACOLUMNS__BUILDER = 'builder' 2968a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.orgKEY__EXTRACOLUMNS__CONFIG = 'config' 3068a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.orgKEY__EXTRACOLUMNS__RESULT_TYPE = 'resultType' 3168a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.orgKEY__EXTRACOLUMNS__TEST = 'test' 327498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__DATAHASH = 'dataHash' 337498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__IS_EDITABLE = 'isEditable' 347498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__IS_EXPORTED = 'isExported' 357498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__IS_STILL_LOADING = 'resultsStillLoading' 3616f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__HEADER__RESULTS_ALL = 'all' 3716f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__HEADER__RESULTS_FAILURES = 'failures' 38ea770f155e72f88e66a4d9c652552517d46a8605commit-bot@chromium.orgKEY__HEADER__SCHEMA_VERSION = 'schemaVersion' 397498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__TIME_NEXT_UPDATE_AVAILABLE = 'timeNextUpdateAvailable' 407498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__TIME_UPDATED = 'timeUpdated' 417498d95bde16eeaa4b20643fb930b6a3be7face1commit-bot@chromium.orgKEY__HEADER__TYPE = 'type' 4216f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__RESULT_TYPE__FAILED = gm_json.JSONKEY_ACTUALRESULTS_FAILED 4316f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__RESULT_TYPE__FAILUREIGNORED = gm_json.JSONKEY_ACTUALRESULTS_FAILUREIGNORED 4416f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__RESULT_TYPE__NOCOMPARISON = gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON 4516f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.orgKEY__RESULT_TYPE__SUCCEEDED = gm_json.JSONKEY_ACTUALRESULTS_SUCCEEDED 4616f418080ff6751e15e0193263149412de9c848acommit-bot@chromium.org 47f9d134da93b8c78e7127efd84c9a26f99a73527eepoger@google.comIMAGE_FILENAME_RE = re.compile(gm_json.IMAGE_FILENAME_PATTERN) 48eb832599b631a09b180ea3615347adba6bd5e363epoger@google.comIMAGE_FILENAME_FORMATTER = '%s_%s.png' # pass in (testname, config) 4931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 50b144271179aaf82cb1151e9dfd8e866747402594epogerPARENT_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) 51defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.orgDEFAULT_ACTUALS_DIR = '.gm-actuals' 52defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.orgDEFAULT_GENERATED_IMAGES_ROOT = os.path.join( 53defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org PARENT_DIRECTORY, '.generated-images') 54defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 55defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org# Define the default set of builders we will process expectations/actuals for. 5631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org# This allows us to ignore builders for which we don't maintain expectations 5731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org# (trybots, Valgrind, ASAN, TSAN), and avoid problems like 5831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org# https://code.google.com/p/skia/issues/detail?id=2036 ('rebaseline_server 5931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org# produces error when trying to add baselines for ASAN/TSAN builders') 60defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.orgDEFAULT_MATCH_BUILDERS_PATTERN_LIST = ['.*'] 61defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.orgDEFAULT_SKIP_BUILDERS_PATTERN_LIST = [ 62defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org '.*-Trybot', '.*Valgrind.*', '.*TSAN.*', '.*ASAN.*'] 6331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 6431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 6531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.orgclass BaseComparisons(object): 6631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Base class for generating summary of comparisons between two image sets. 6731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 6831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 6931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org def get_results_of_type(self, results_type): 7031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Return results of some/all tests (depending on 'results_type' parameter). 7131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 7231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Args: 7331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org results_type: string describing which types of results to include; must 7431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org be one of the RESULTS_* constants 7531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 7631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Results are returned in a dictionary as output by ImagePairSet.as_dict(). 7731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 7831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return self._results[results_type] 7931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 8031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org def get_packaged_results_of_type(self, results_type, reload_seconds=None, 8131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org is_editable=False, is_exported=True): 8231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Package the results of some/all tests as a complete response_dict. 8331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 8431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Args: 8531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org results_type: string indicating which set of results to return; 8631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org must be one of the RESULTS_* constants 8731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org reload_seconds: if specified, note that new results may be available once 8831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org these results are reload_seconds old 8931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org is_editable: whether clients are allowed to submit new baselines 9031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org is_exported: whether these results are being made available to other 9131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org network hosts 9231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 9331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org response_dict = self._results[results_type] 9431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org time_updated = self.get_timestamp() 9568a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.org response_dict[imagepairset.KEY__ROOT__HEADER] = { 9631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__SCHEMA_VERSION: ( 9768a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.org VALUE__HEADER__SCHEMA_VERSION), 9831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 9931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # Timestamps: 10031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # 1. when this data was last updated 10131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # 2. when the caller should check back for new data (if ever) 10231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__TIME_UPDATED: time_updated, 10331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__TIME_NEXT_UPDATE_AVAILABLE: ( 10431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org (time_updated+reload_seconds) if reload_seconds else None), 10531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 10631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # The type we passed to get_results_of_type() 10731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__TYPE: results_type, 10831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 10931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # Hash of dataset, which the client must return with any edits-- 11031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # this ensures that the edits were made to a particular dataset. 11131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__DATAHASH: str(hash(repr( 11268a3815401f461976f76891d0477cb1440fa0abacommit-bot@chromium.org response_dict[imagepairset.KEY__ROOT__IMAGEPAIRS]))), 11331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 11431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # Whether the server will accept edits back. 11531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__IS_EDITABLE: is_editable, 11631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 11731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org # Whether the service is accessible from other hosts. 11831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org KEY__HEADER__IS_EXPORTED: is_exported, 11931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org } 12031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return response_dict 12131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 12231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org def get_timestamp(self): 12331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Return the time at which this object was created, in seconds past epoch 12431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org (UTC). 12531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 12631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return self._timestamp 12731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 128defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org _match_builders_pattern_list = [ 129defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org re.compile(p) for p in DEFAULT_MATCH_BUILDERS_PATTERN_LIST] 130defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org _skip_builders_pattern_list = [ 131defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org re.compile(p) for p in DEFAULT_SKIP_BUILDERS_PATTERN_LIST] 132defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 133defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org def set_match_builders_pattern_list(self, pattern_list): 134defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org """Override the default set of builders we should process. 135defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 136defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org The default is DEFAULT_MATCH_BUILDERS_PATTERN_LIST . 137defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 138defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org Note that skip_builders_pattern_list overrides this; regardless of whether a 139defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org builder is in the "match" list, if it's in the "skip" list, we will skip it. 140defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 141defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org Args: 142defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org pattern_list: list of regex patterns; process builders that match any 143defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org entry within this list 144defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org """ 145defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org if pattern_list == None: 146defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org pattern_list = [] 147defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org self._match_builders_pattern_list = [re.compile(p) for p in pattern_list] 148defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 149defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org def set_skip_builders_pattern_list(self, pattern_list): 150defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org """Override the default set of builders we should skip while processing. 151defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 152defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org The default is DEFAULT_SKIP_BUILDERS_PATTERN_LIST . 153defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 154defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org This overrides match_builders_pattern_list; regardless of whether a 155defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org builder is in the "match" list, if it's in the "skip" list, we will skip it. 156defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 157defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org Args: 158defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org pattern_list: list of regex patterns; skip builders that match any 159defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org entry within this list 160defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org """ 161defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org if pattern_list == None: 162defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org pattern_list = [] 163defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org self._skip_builders_pattern_list = [re.compile(p) for p in pattern_list] 164defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org 165defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org def _ignore_builder(self, builder): 166defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org """Returns True if we should skip processing this builder. 16731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 16831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Args: 16931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org builder: name of this builder, as a string 17031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 17131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Returns: 17231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org True if we should ignore expectations and actuals for this builder. 17331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 174defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org for pattern in self._skip_builders_pattern_list: 17531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org if pattern.match(builder): 17631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return True 177defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org for pattern in self._match_builders_pattern_list: 178defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org if pattern.match(builder): 179defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org return False 180defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org return True 18131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 1827418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org def _read_builder_dicts_from_root(self, root, pattern='*.json'): 18331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Read all JSON dictionaries within a directory tree. 18431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 1857418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org Skips any dictionaries belonging to a builder we have chosen to ignore. 1867418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 18731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Args: 18831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org root: path to root of directory tree 18931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org pattern: which files to read within root (fnmatch-style pattern) 19031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 19131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Returns: 19231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org A meta-dictionary containing all the JSON dictionaries found within 1937418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org the directory tree, keyed by builder name (the basename of the directory 1947418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org where each JSON dictionary was found). 19531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 19631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Raises: 19731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org IOError if root does not refer to an existing directory 19831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 1997418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org # I considered making this call _read_dicts_from_root(), but I decided 2007418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org # it was better to prune out the ignored builders within the os.walk(). 20131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org if not os.path.isdir(root): 20231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org raise IOError('no directory found at path %s' % root) 20331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org meta_dict = {} 20431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org for dirpath, dirnames, filenames in os.walk(root): 20531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org for matching_filename in fnmatch.filter(filenames, pattern): 20631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org builder = os.path.basename(dirpath) 207defe6fdbc8edb2df0887c007450a8d8cc446f420commit-bot@chromium.org if self._ignore_builder(builder): 20831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org continue 2097418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org full_path = os.path.join(dirpath, matching_filename) 2107418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org meta_dict[builder] = gm_json.LoadFromFile(full_path) 2117418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org return meta_dict 2127418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 2137418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org def _read_dicts_from_root(self, root, pattern='*.json'): 2147418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org """Read all JSON dictionaries within a directory tree. 2157418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 2167418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org Args: 2177418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org root: path to root of directory tree 2187418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org pattern: which files to read within root (fnmatch-style pattern) 2197418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 2207418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org Returns: 2217418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org A meta-dictionary containing all the JSON dictionaries found within 2227418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org the directory tree, keyed by the pathname (relative to root) of each JSON 2237418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org dictionary. 2247418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 2257418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org Raises: 2267418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org IOError if root does not refer to an existing directory 2277418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org """ 2287418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org if not os.path.isdir(root): 2297418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org raise IOError('no directory found at path %s' % root) 2307418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org meta_dict = {} 2317418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org for abs_dirpath, dirnames, filenames in os.walk(root): 2327418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org rel_dirpath = os.path.relpath(abs_dirpath, root) 2337418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org for matching_filename in fnmatch.filter(filenames, pattern): 2347418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org abs_path = os.path.join(abs_dirpath, matching_filename) 2357418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org rel_path = os.path.join(rel_dirpath, matching_filename) 2367418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org meta_dict[rel_path] = gm_json.LoadFromFile(abs_path) 23731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return meta_dict 23831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 23931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org @staticmethod 2404cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org def _read_noncomment_lines(path): 2414cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org """Return a list of all noncomment lines within a file. 2424cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org 2434cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org (A "noncomment" line is one that does not start with a '#'.) 2444cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org 2454cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org Args: 2464cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org path: path to file 2474cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org """ 2484cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org lines = [] 2494cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org with open(path, 'r') as fh: 2504cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org for line in fh: 2514cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org if not line.startswith('#'): 2524cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org lines.append(line.strip()) 2534cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org return lines 2544cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org 2554cef1be82193a9d527f7b1f873197c443d0dde2ecommit-bot@chromium.org @staticmethod 25631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org def _create_relative_url(hashtype_and_digest, test_name): 25731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """Returns the URL for this image, relative to GM_ACTUALS_ROOT_HTTP_URL. 25831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 25931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org If we don't have a record of this image, returns None. 26031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org 26131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org Args: 26231d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org hashtype_and_digest: (hash_type, hash_digest) tuple, or None if we 26331d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org don't have a record of this image 26431d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org test_name: string; name of the GM test that created this image 26531d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org """ 26631d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org if not hashtype_and_digest: 26731d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return None 26831d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org return gm_json.CreateGmRelativeUrl( 26931d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org test_name=test_name, 27031d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org hash_type=hashtype_and_digest[0], 27131d0b3d806a1aa86b7edaa442b3821f5d548e184commit-bot@chromium.org hash_digest=hashtype_and_digest[1]) 2723eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org 2733eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org @staticmethod 2743eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org def combine_subdicts(input_dict): 2753eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org """ Flatten out a dictionary structure by one level. 2763eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org 2773eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org Input: 2783eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org { 2797418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_A1 : { 2807418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_B1 : VALUE_B1, 2813eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org }, 2827418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_A2 : { 2837418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_B2 : VALUE_B2, 2843eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org } 2853eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org } 2863eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org 2873eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org Output: 2883eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org { 2897418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_B1 : VALUE_B1, 2907418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org KEY_B2 : VALUE_B2, 2913eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org } 2923eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org 2933eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org If this would result in any repeated keys, it will raise an Exception. 2943eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org """ 2953eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org output_dict = {} 2963eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org for key, subdict in input_dict.iteritems(): 2973eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org for subdict_key, subdict_value in subdict.iteritems(): 2983eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org if subdict_key in output_dict: 2993eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org raise Exception('duplicate key %s in combine_subdicts' % subdict_key) 3003eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org output_dict[subdict_key] = subdict_value 3013eb77e4d5a381fa55197f6bd03c599e709146069commit-bot@chromium.org return output_dict 3027418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org 3037418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org @staticmethod 3047418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org def get_multilevel(input_dict, *keys): 3057418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org """ Returns input_dict[key1][key2][...], or None if any key is not found. 3067418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org """ 3077418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org for key in keys: 3087418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org if input_dict == None: 3097418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org return None 3107418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org input_dict = input_dict.get(key, None) 3117418bd8cad3576294b48dd8e5015301e184c6af1commit-bot@chromium.org return input_dict 312