1 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 6 """ Utilities for dealing with builder names. This module obtains its attributes 7 dynamically from builder_name_schema.json. """ 8 9 10 import json 11 import os 12 13 14 # All of these global variables are filled in by _LoadSchema(). 15 16 # The full schema. 17 BUILDER_NAME_SCHEMA = None 18 19 # Character which separates parts of a builder name. 20 BUILDER_NAME_SEP = None 21 22 # Builder roles. 23 BUILDER_ROLE_CANARY = 'Canary' 24 BUILDER_ROLE_BUILD = 'Build' 25 BUILDER_ROLE_HOUSEKEEPER = 'Housekeeper' 26 BUILDER_ROLE_INFRA = 'Infra' 27 BUILDER_ROLE_PERF = 'Perf' 28 BUILDER_ROLE_TEST = 'Test' 29 BUILDER_ROLE_UPLOAD = 'Upload' 30 BUILDER_ROLE_CALMBENCH = "Calmbench" 31 BUILDER_ROLES = (BUILDER_ROLE_CANARY, 32 BUILDER_ROLE_BUILD, 33 BUILDER_ROLE_HOUSEKEEPER, 34 BUILDER_ROLE_INFRA, 35 BUILDER_ROLE_PERF, 36 BUILDER_ROLE_TEST, 37 BUILDER_ROLE_UPLOAD, 38 BUILDER_ROLE_CALMBENCH) 39 40 41 def _LoadSchema(): 42 """ Load the builder naming schema from the JSON file. """ 43 44 def _UnicodeToStr(obj): 45 """ Convert all unicode strings in obj to Python strings. """ 46 if isinstance(obj, unicode): 47 return str(obj) 48 elif isinstance(obj, dict): 49 return dict(map(_UnicodeToStr, obj.iteritems())) 50 elif isinstance(obj, list): 51 return list(map(_UnicodeToStr, obj)) 52 elif isinstance(obj, tuple): 53 return tuple(map(_UnicodeToStr, obj)) 54 55 builder_name_json_filename = os.path.join( 56 os.path.dirname(__file__), 'builder_name_schema.json') 57 builder_name_schema_json = json.load(open(builder_name_json_filename)) 58 59 global BUILDER_NAME_SCHEMA 60 BUILDER_NAME_SCHEMA = _UnicodeToStr( 61 builder_name_schema_json['builder_name_schema']) 62 63 global BUILDER_NAME_SEP 64 BUILDER_NAME_SEP = _UnicodeToStr( 65 builder_name_schema_json['builder_name_sep']) 66 67 # Since the builder roles are dictionary keys, just assert that the global 68 # variables above account for all of them. 69 assert len(BUILDER_ROLES) == len(BUILDER_NAME_SCHEMA) 70 for role in BUILDER_ROLES: 71 assert role in BUILDER_NAME_SCHEMA 72 73 74 _LoadSchema() 75 76 77 def MakeBuilderName(role, extra_config=None, **kwargs): 78 schema = BUILDER_NAME_SCHEMA.get(role) 79 if not schema: 80 raise ValueError('%s is not a recognized role.' % role) 81 for k, v in kwargs.iteritems(): 82 if BUILDER_NAME_SEP in v: 83 raise ValueError('%s not allowed in %s.' % (BUILDER_NAME_SEP, v)) 84 if not k in schema: 85 raise ValueError('Schema does not contain "%s": %s' %(k, schema)) 86 if extra_config and BUILDER_NAME_SEP in extra_config: 87 raise ValueError('%s not allowed in %s.' % (BUILDER_NAME_SEP, 88 extra_config)) 89 name_parts = [role] 90 name_parts.extend([kwargs[attribute] for attribute in schema]) 91 if extra_config: 92 name_parts.append(extra_config) 93 return BUILDER_NAME_SEP.join(name_parts) 94 95 96 def DictForBuilderName(builder_name): 97 """Makes a dictionary containing details about the builder from its name.""" 98 split_name = builder_name.split(BUILDER_NAME_SEP) 99 100 def pop_front(): 101 try: 102 return split_name.pop(0) 103 except: 104 raise ValueError('Invalid builder name: %s' % builder_name) 105 106 result = {} 107 if split_name[0] in BUILDER_NAME_SCHEMA.keys(): 108 key_list = BUILDER_NAME_SCHEMA[split_name[0]] 109 result['role'] = pop_front() 110 for key in key_list: 111 result[key] = pop_front() 112 if split_name: 113 result['extra_config'] = pop_front() 114 if split_name: 115 raise ValueError('Invalid builder name: %s' % builder_name) 116 else: 117 raise ValueError('Invalid builder name: %s' % builder_name) 118 return result 119 120 121