| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2013 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 def _LoadSchema(): | |
| 15 """ Load the builder naming schema from the JSON file. """ | |
| 16 | |
| 17 def _UnicodeToStr(obj): | |
| 18 """ Convert all unicode strings in obj to Python strings. """ | |
| 19 if isinstance(obj, unicode): | |
| 20 return str(obj) | |
| 21 elif isinstance(obj, dict): | |
| 22 return dict(map(_UnicodeToStr, obj.iteritems())) | |
| 23 elif isinstance(obj, list): | |
| 24 return list(map(_UnicodeToStr, obj)) | |
| 25 elif isinstance(obj, tuple): | |
| 26 return tuple(map(_UnicodeToStr, obj)) | |
| 27 else: | |
| 28 return obj | |
| 29 | |
| 30 builder_name_json_filename = os.path.join( | |
| 31 os.path.dirname(__file__), 'builder_name_schema.json') | |
| 32 builder_name_schema_json = json.load(open(builder_name_json_filename)) | |
| 33 for k, v in builder_name_schema_json.iteritems(): | |
| 34 globals()[str(k).upper()] = _UnicodeToStr(v) | |
| 35 | |
| 36 # Roles specify different types of builders. | |
| 37 builder_role_template = 'BUILDER_ROLE_%s' | |
| 38 | |
| 39 #pylint: disable=E0602 | |
| 40 for role in BUILDER_NAME_SCHEMA.keys(): | |
| 41 globals()[builder_role_template % role.upper()] = role | |
| 42 | |
| 43 _LoadSchema() | |
| 44 | |
| 45 | |
| 46 def MakeBuilderName(role, extra_config=None, is_trybot=False, **kwargs): | |
| 47 #pylint: disable=E0602 | |
| 48 schema = BUILDER_NAME_SCHEMA.get(role) | |
| 49 if not schema: | |
| 50 raise ValueError('%s is not a recognized role.' % role) | |
| 51 for k, v in kwargs.iteritems(): | |
| 52 if BUILDER_NAME_SEP in v: | |
| 53 raise ValueError('%s not allowed in %s.' % (BUILDER_NAME_SEP, v)) | |
| 54 if not k in schema: | |
| 55 raise ValueError('Schema does not contain "%s": %s' %(k, schema)) | |
| 56 if extra_config and BUILDER_NAME_SEP in extra_config: | |
| 57 raise ValueError('%s not allowed in %s.' % (BUILDER_NAME_SEP, | |
| 58 extra_config)) | |
| 59 name_parts = [role] | |
| 60 name_parts.extend([kwargs[attribute] for attribute in schema]) | |
| 61 if extra_config: | |
| 62 name_parts.append(extra_config) | |
| 63 if is_trybot: | |
| 64 name_parts.append(TRYBOT_NAME_SUFFIX) | |
| 65 return BUILDER_NAME_SEP.join(name_parts) | |
| 66 | |
| 67 | |
| 68 def BuilderNameFromObject(obj, is_trybot=False): | |
| 69 """Create a builder name based on properties of the given object. | |
| 70 | |
| 71 Args: | |
| 72 obj: the object from which to create the builder name. The object must | |
| 73 have as properties: | |
| 74 - A valid builder role, as defined in the JSON file | |
| 75 - All properties listed in the JSON file for that role | |
| 76 - Optionally, an extra_config property | |
| 77 is_trybot: bool; whether or not the builder is a trybot. | |
| 78 Returns: | |
| 79 string which combines the properties of the given object into a valid | |
| 80 builder name. | |
| 81 """ | |
| 82 #pylint: disable=E0602 | |
| 83 schema = BUILDER_NAME_SCHEMA.get(obj.role) | |
| 84 if not schema: | |
| 85 raise ValueError('%s is not a recognized role.' % role) | |
| 86 name_parts = [obj.role] | |
| 87 for attr_name in schema: | |
| 88 attr_val = getattr(obj, attr_name) | |
| 89 name_parts.append(attr_val) | |
| 90 extra_config = getattr(obj, 'extra_config', None) | |
| 91 if extra_config: | |
| 92 name_parts.append(extra_config) | |
| 93 if is_trybot: | |
| 94 name_parts.append(TRYBOT_NAME_SUFFIX) | |
| 95 return BUILDER_NAME_SEP.join(name_parts) | |
| 96 | |
| 97 | |
| 98 def IsTrybot(builder_name): | |
| 99 """ Returns true if builder_name refers to a trybot (as opposed to a | |
| 100 waterfall bot). """ | |
| 101 #pylint: disable=E0602 | |
| 102 return builder_name.endswith(TRYBOT_NAME_SUFFIX) | |
| 103 | |
| 104 | |
| 105 def GetWaterfallBot(builder_name): | |
| 106 """Returns the name of the waterfall bot for this builder. If it is not a | |
| 107 trybot, builder_name is returned unchanged. If it is a trybot the name is | |
| 108 returned without the trybot suffix.""" | |
| 109 #pylint: disable=E0602 | |
| 110 if not IsTrybot(builder_name): | |
| 111 return builder_name | |
| 112 return _WithoutSuffix(builder_name, BUILDER_NAME_SEP + TRYBOT_NAME_SUFFIX) | |
| 113 | |
| 114 | |
| 115 def _WithoutSuffix(string, suffix): | |
| 116 """ Returns a copy of string 'string', but with suffix 'suffix' removed. | |
| 117 Raises ValueError if string does not end with suffix. """ | |
| 118 if not string.endswith(suffix): | |
| 119 raise ValueError('_WithoutSuffix: string %s does not end with suffix %s' % ( | |
| 120 string, suffix)) | |
| 121 return string[:-len(suffix)] | |
| 122 | |
| 123 | |
| 124 def DictForBuilderName(builder_name): | |
| 125 """Makes a dictionary containing details about the builder from its name.""" | |
| 126 #pylint: disable=E0602 | |
| 127 split_name = builder_name.split(BUILDER_NAME_SEP) | |
| 128 | |
| 129 def pop_front(): | |
| 130 try: | |
| 131 return split_name.pop(0) | |
| 132 except: | |
| 133 raise ValueError('Invalid builder name: %s' % builder_name) | |
| 134 | |
| 135 result = {'is_trybot': False} | |
| 136 | |
| 137 if split_name[-1] == TRYBOT_NAME_SUFFIX: | |
| 138 result['is_trybot'] = True | |
| 139 split_name.pop() | |
| 140 | |
| 141 if split_name[0] in BUILDER_NAME_SCHEMA.keys(): | |
| 142 key_list = BUILDER_NAME_SCHEMA[split_name[0]] | |
| 143 result['role'] = pop_front() | |
| 144 for key in key_list: | |
| 145 result[key] = pop_front() | |
| 146 if split_name: | |
| 147 result['extra_config'] = pop_front() | |
| 148 if split_name: | |
| 149 raise ValueError('Invalid builder name: %s' % builder_name) | |
| 150 else: | |
| 151 raise ValueError('Invalid builder name: %s' % builder_name) | |
| 152 return result | |
| 153 | |
| 154 | |
| OLD | NEW |