1a8f774549e35b743afae35e3436f73e8849e869depoger#!/usr/bin/python 2a8f774549e35b743afae35e3436f73e8849e869depoger# Copyright (c) 2014 The Chromium Authors. All rights reserved. 3a8f774549e35b743afae35e3436f73e8849e869depoger# Use of this source code is governed by a BSD-style license that can be 4a8f774549e35b743afae35e3436f73e8849e869depoger# found in the LICENSE file. 5a8f774549e35b743afae35e3436f73e8849e869depoger 6a8f774549e35b743afae35e3436f73e8849e869depoger"""Utility to duplicate a config in some subset of our GM expectation files. 7a8f774549e35b743afae35e3436f73e8849e869depoger 8a8f774549e35b743afae35e3436f73e8849e869depogerCreated for http://skbug.com/2752 ('split existing "gpu" GM results into "gl" 9a8f774549e35b743afae35e3436f73e8849e869depogerand "gles"') 10a8f774549e35b743afae35e3436f73e8849e869depoger 11a8f774549e35b743afae35e3436f73e8849e869depogerRun with -h to see usage. 12a8f774549e35b743afae35e3436f73e8849e869depoger 13a8f774549e35b743afae35e3436f73e8849e869depogerExample command lines: 14a8f774549e35b743afae35e3436f73e8849e869depoger copy_config.py gl gles '.*Mac10.7.*' 15a8f774549e35b743afae35e3436f73e8849e869depoger 16a8f774549e35b743afae35e3436f73e8849e869depogerTODO(epoger): Once https://codereview.chromium.org/397103003/ is committed, 17a8f774549e35b743afae35e3436f73e8849e869depogerwe should add a unittest. Until then, we can test this as follows: 18a8f774549e35b743afae35e3436f73e8849e869depoger 19a8f774549e35b743afae35e3436f73e8849e869depogerOLD=expectations/gm && NEW=/tmp/expectations && \ 20a8f774549e35b743afae35e3436f73e8849e869depoger rm -rf $NEW && \ 21a8f774549e35b743afae35e3436f73e8849e869depoger cp -a $OLD $NEW && \ 22a8f774549e35b743afae35e3436f73e8849e869depoger gm/copy_config.py 8888 8888-copy '.*Mac10.7.*' \ 23a8f774549e35b743afae35e3436f73e8849e869depoger --expectations-root $NEW && \ 24a8f774549e35b743afae35e3436f73e8849e869depoger diff --recursive $OLD $NEW 25a8f774549e35b743afae35e3436f73e8849e869depoger""" 26a8f774549e35b743afae35e3436f73e8849e869depoger__author__ = 'Elliot Poger' 27a8f774549e35b743afae35e3436f73e8849e869depoger 28a8f774549e35b743afae35e3436f73e8849e869depogerimport argparse 29a8f774549e35b743afae35e3436f73e8849e869depogerimport os 30a8f774549e35b743afae35e3436f73e8849e869depogerimport re 31a8f774549e35b743afae35e3436f73e8849e869depoger 32a8f774549e35b743afae35e3436f73e8849e869depogerimport gm_json 33a8f774549e35b743afae35e3436f73e8849e869depoger 34a8f774549e35b743afae35e3436f73e8849e869depogerDEFAULT_EXPECTATIONS_ROOT = os.path.join( 35a8f774549e35b743afae35e3436f73e8849e869depoger os.path.dirname(__file__), os.pardir, 'expectations', 'gm') 36a8f774549e35b743afae35e3436f73e8849e869depogerIMAGE_FILENAME_RE = re.compile(gm_json.IMAGE_FILENAME_PATTERN) 37a8f774549e35b743afae35e3436f73e8849e869depoger 38a8f774549e35b743afae35e3436f73e8849e869depoger 39a8f774549e35b743afae35e3436f73e8849e869depogerclass Copier(object): 40a8f774549e35b743afae35e3436f73e8849e869depoger 41a8f774549e35b743afae35e3436f73e8849e869depoger def __init__(self, args): 42a8f774549e35b743afae35e3436f73e8849e869depoger """ 43a8f774549e35b743afae35e3436f73e8849e869depoger Params: 44a8f774549e35b743afae35e3436f73e8849e869depoger args: the Namespace object generated by argparse.parse_args() 45a8f774549e35b743afae35e3436f73e8849e869depoger """ 46a8f774549e35b743afae35e3436f73e8849e869depoger self._args = args 47a8f774549e35b743afae35e3436f73e8849e869depoger 48a8f774549e35b743afae35e3436f73e8849e869depoger def run(self): 49a8f774549e35b743afae35e3436f73e8849e869depoger """Perform all the duplications.""" 50a8f774549e35b743afae35e3436f73e8849e869depoger for path in self._get_file_list(): 51a8f774549e35b743afae35e3436f73e8849e869depoger self._duplicate_config(path=path, 52a8f774549e35b743afae35e3436f73e8849e869depoger old=self._args.old_config_name, 53a8f774549e35b743afae35e3436f73e8849e869depoger new=self._args.new_config_name) 54a8f774549e35b743afae35e3436f73e8849e869depoger 55a8f774549e35b743afae35e3436f73e8849e869depoger def _duplicate_config(self, path, old, new): 56a8f774549e35b743afae35e3436f73e8849e869depoger """Duplicates all instances of a config within a GM expectations file. 57a8f774549e35b743afae35e3436f73e8849e869depoger 58a8f774549e35b743afae35e3436f73e8849e869depoger Params: 59a8f774549e35b743afae35e3436f73e8849e869depoger path: path to file which will be modified in place 60a8f774549e35b743afae35e3436f73e8849e869depoger old: old config name 61a8f774549e35b743afae35e3436f73e8849e869depoger new: new config name 62a8f774549e35b743afae35e3436f73e8849e869depoger """ 63a8f774549e35b743afae35e3436f73e8849e869depoger dic = gm_json.LoadFromFile(file_path=path) 64a8f774549e35b743afae35e3436f73e8849e869depoger expected_results = dic[gm_json.JSONKEY_EXPECTEDRESULTS] 65a8f774549e35b743afae35e3436f73e8849e869depoger orig_keys = expected_results.keys() 66a8f774549e35b743afae35e3436f73e8849e869depoger for key in orig_keys: 67a8f774549e35b743afae35e3436f73e8849e869depoger result = expected_results[key] 68a8f774549e35b743afae35e3436f73e8849e869depoger (testname, config) = IMAGE_FILENAME_RE.match(key).groups() 69a8f774549e35b743afae35e3436f73e8849e869depoger if config == old: 70a8f774549e35b743afae35e3436f73e8849e869depoger config = new 71a8f774549e35b743afae35e3436f73e8849e869depoger key = '%s_%s.png' % (testname, config) 72a8f774549e35b743afae35e3436f73e8849e869depoger expected_results[key] = result 73a8f774549e35b743afae35e3436f73e8849e869depoger gm_json.WriteToFile(json_dict=dic, file_path=path) 74a8f774549e35b743afae35e3436f73e8849e869depoger 75a8f774549e35b743afae35e3436f73e8849e869depoger def _get_file_list(self): 76a8f774549e35b743afae35e3436f73e8849e869depoger """Returns the list of files we want to operate on (the complete path 77a8f774549e35b743afae35e3436f73e8849e869depoger to each file).""" 78a8f774549e35b743afae35e3436f73e8849e869depoger root = self._args.expectations_root 79a8f774549e35b743afae35e3436f73e8849e869depoger regex = re.compile(self._args.builder_name_pattern) 80a8f774549e35b743afae35e3436f73e8849e869depoger return [os.path.join(root, builder, 'expected-results.json') 81a8f774549e35b743afae35e3436f73e8849e869depoger for builder in os.listdir(root) 82a8f774549e35b743afae35e3436f73e8849e869depoger if regex.match(builder)] 83a8f774549e35b743afae35e3436f73e8849e869depoger 84a8f774549e35b743afae35e3436f73e8849e869depoger 85a8f774549e35b743afae35e3436f73e8849e869depogerdef main(): 86a8f774549e35b743afae35e3436f73e8849e869depoger parser = argparse.ArgumentParser() 87a8f774549e35b743afae35e3436f73e8849e869depoger parser.add_argument('old_config_name', 88a8f774549e35b743afae35e3436f73e8849e869depoger help=('Config we want to duplicate.')) 89a8f774549e35b743afae35e3436f73e8849e869depoger parser.add_argument('new_config_name', 90a8f774549e35b743afae35e3436f73e8849e869depoger help=('Name of the new config we want to create.')) 91a8f774549e35b743afae35e3436f73e8849e869depoger parser.add_argument('builder_name_pattern', 92a8f774549e35b743afae35e3436f73e8849e869depoger help=('Regex pattern describing which builders we want ' 93a8f774549e35b743afae35e3436f73e8849e869depoger 'to make the duplication for; \'.*\' to perform ' 94a8f774549e35b743afae35e3436f73e8849e869depoger 'the duplication on all builders.')) 95a8f774549e35b743afae35e3436f73e8849e869depoger parser.add_argument('--expectations-root', 96a8f774549e35b743afae35e3436f73e8849e869depoger default=DEFAULT_EXPECTATIONS_ROOT, 97a8f774549e35b743afae35e3436f73e8849e869depoger help=('Root of the GM expectations dir; defaults to ' 98a8f774549e35b743afae35e3436f73e8849e869depoger '%(default)s')) 99a8f774549e35b743afae35e3436f73e8849e869depoger args = parser.parse_args() 100a8f774549e35b743afae35e3436f73e8849e869depoger copier = Copier(args) 101a8f774549e35b743afae35e3436f73e8849e869depoger copier.run() 102a8f774549e35b743afae35e3436f73e8849e869depoger 103a8f774549e35b743afae35e3436f73e8849e869depogerif __name__ == '__main__': 104a8f774549e35b743afae35e3436f73e8849e869depoger main() 105