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