2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Helper functions for accessing the issue tracker in a pythonic way."""
11 # pylint: disable=F0401
13 import gdata.projecthosting.client
14 # pylint: enable=F0401
17 DEFAULT_TRACKER_SOURCE = "chromite-tracker-access-1.0"
18 VERBOSE = True # Set to True to get extra debug info...
21 class TrackerAccess(object):
22 """Class for accessing the tracker on code.google.com."""
24 def __init__(self, email="", password="",
25 tracker_source=DEFAULT_TRACKER_SOURCE):
26 """TrackerAccess constructor.
29 email: The email address to Login with; may be "" for anonymous access.
30 password: The password that goes with the email address; may be "" if
32 tracker_source: A string describing this program. This can be anything
33 you like but should should give some indication of which
34 app is making the request.
38 self._password = password
39 self._tracker_source = tracker_source
41 # This will be initted on first login...
42 self._tracker_client = None
45 """Login, if needed. This may be safely called more than once.
47 Commands will call this function as their first line, so the client
48 of this class need not call it themselves unless trying to debug login
51 This function should be called even if we're accessing anonymously.
53 # Bail immediately if we've already logged in...
54 if self._tracker_client is not None:
57 self._tracker_client = gdata.projecthosting.client.ProjectHostingClient()
58 if self._email and self._password:
59 self._tracker_client.client_login(self._email, self._password,
60 source=self._tracker_source,
61 service="code", account_type='GOOGLE')
63 def GetKeyedLabels(self, project_name, issue_id):
64 """Get labels of the form "Key-Value" attached to the given issue.
66 Any labels that don't have a dash in them are ignored.
69 project_name: The tracker project to query.
70 issue_id: The ID of the issue to query; should be an int but a string
71 will probably work too.
74 A dictionary mapping key/value pairs from the issue's labels, like:
85 # Construct the query...
86 query = gdata.projecthosting.client.Query(issue_id=issue_id)
88 feed = self._tracker_client.get_issues(project_name, query=query)
89 except gdata.client.RequestError as e:
91 print >> sys.stderr, "ERROR: Unable to access bug %s:%s: %s" % (
92 project_name, issue_id, str(e))
95 # There should be exactly one result...
96 assert len(feed.entry) == 1, "Expected exactly 1 result"
99 # We only care about labels that look like: Key-Value
100 # We'll return a dictionary of those.
102 for label in entry.label:
103 if "-" in label.text:
104 label_key, label_val = label.text.split("-", 1)
105 keyed_labels[label_key] = label_val
110 def _TestGetKeyedLabels(project_name, email, passwordFile, *args):
111 """Test code for GetKeyedLabels().
114 project_name: The name of the project we're looking at.
115 email: The email address to use to login. May be ""
116 passwordFile: A file containing the password for the email address.
117 May be "" if email is "" for anon access.
118 args: A list of bug IDs to query.
121 # If password was specified as a file, read it.
123 password = open(passwordFile, "r").read().strip()
127 ta = TrackerAccess(email, password)
130 print "No bugs were specified"
132 for bug_id in bug_ids:
133 print bug_id, ta.GetKeyedLabels(project_name, int(bug_id))
136 def _DoHelp(commands, *args):
137 """Print help for the script."""
139 if len(args) >= 2 and args[0] == "help" and args[1] in commands:
140 # If called with arguments 'help' and 'command', show that commands's doc.
141 command_name = args[1]
142 print commands[command_name].__doc__
144 # Something else: show generic help...
146 "Usage %s <command> <command args>\n"
150 ) % (sys.argv[0], pprint.pformat(["help"] + sorted(commands)))
154 """Main function of the script."""
157 "TestGetKeyedLabels": _TestGetKeyedLabels,
160 if len(sys.argv) <= 1 or sys.argv[1] not in commands:
161 # Argument 1 isn't in list of commands; show help and pass all arguments...
162 _DoHelp(commands, *sys.argv[1:])
164 command_name = sys.argv[1]
165 commands[command_name](*sys.argv[2:])
167 if __name__ == "__main__":