buildbot_globals.py revision 9f8e282901752e95e3b43059a19f08ea0a1a073e
1#!/usr/bin/python
2
3# Copyright (c) 2013 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""
8Provides read access to buildbot's global_variables.json .
9"""
10
11
12from contextlib import closing
13
14import HTMLParser
15import json
16import re
17import svn
18import sys
19import urllib2
20
21
22_global_vars = None
23
24
25GLOBAL_VARS_JSON_URL = ('https://skia.googlesource.com/buildbot/+'
26                        '/master/site_config/global_variables.json')
27
28
29class GlobalVarsRetrievalError(Exception):
30  """Exception which is raised when the global_variables.json file cannot be
31  retrieved from the Skia buildbot repository."""
32  pass
33
34
35class JsonDecodeError(Exception):
36  """Exception which is raised when the global_variables.json file cannot be
37  interpreted as JSON. This may be due to the file itself being incorrectly
38  formatted or due to an incomplete or corrupted downloaded version of the file.
39  """
40  pass
41
42
43class NoSuchGlobalVariable(KeyError):
44  """Exception which is raised when a given variable is not found in the
45  global_variables.json file."""
46  pass
47
48
49def retrieve_from_googlesource(url):
50  """Retrieve the given file from GoogleSource's HTTP interface, trimming the
51  extraneous HTML. Intended to be a GoogleSource equivalent of "svn cat".
52
53  This just returns the unescaped contents of the first <pre> tag which matches
54  our expectations for GoogleSource's HTTP interface. If that interface changes,
55  this function will almost surely break.
56
57  Args:
58      url: string; the URL of the file to retrieve.
59  Returns:
60      The contents of the file in GoogleSource, stripped of the extra HTML from
61          the HTML interface.
62  """
63  with closing(urllib2.urlopen(url)) as f:
64    contents = f.read()
65    pre_open = '<pre class="git-blob prettyprint linenums lang-(\w+)">'
66    pre_close = '</pre>'
67    matched_tag = re.search(pre_open, contents).group()
68    start_index = contents.find(matched_tag)
69    end_index = contents.find(pre_close)
70    parser = HTMLParser.HTMLParser()
71    return parser.unescape(contents[start_index + len(matched_tag):end_index])
72
73
74def Get(var_name):
75  """Return the value associated with this name in global_variables.json.
76
77  Args:
78      var_name: string; the variable to look up.
79  Returns:
80      The value of the variable.
81  Raises:
82      NoSuchGlobalVariable if there is no variable with that name.
83  """
84  global _global_vars
85  if not _global_vars:
86    try:
87      global_vars_text = retrieve_from_googlesource(GLOBAL_VARS_JSON_URL)
88    except Exception:
89      raise GlobalVarsRetrievalError('Failed to retrieve %s.' %
90                                     GLOBAL_VARS_JSON_URL)
91    try:
92      _global_vars = json.loads(global_vars_text)
93    except ValueError as e:
94      raise JsonDecodeError(e.message + '\n' + global_vars_text)
95  try:
96    return _global_vars[var_name]['value']
97  except KeyError:
98    raise NoSuchGlobalVariable(var_name)
99
100
101if __name__ == '__main__':
102  print Get(sys.argv[1])
103