1 # Copyright (c) 2010 The Chromium OS 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.
5 """Helper functions for accessing the issue tracker in a pythonic way."""
7 from __future__ import print_function
12 # pylint: disable=F0401
14 import gdata.projecthosting.client
15 # pylint: enable=F0401
18 DEFAULT_TRACKER_SOURCE = "chromite-tracker-access-1.0"
19 VERBOSE = True # Set to True to get extra debug info...
22 class TrackerAccess(object):
23 """Class for accessing the tracker on code.google.com."""
25 def __init__(self, email="", password="",
26 tracker_source=DEFAULT_TRACKER_SOURCE):
27 """TrackerAccess constructor.
30 email: The email address to Login with; may be "" for anonymous access.
31 password: The password that goes with the email address; may be "" if
33 tracker_source: A string describing this program. This can be anything
34 you like but should should give some indication of which
35 app is making the request.
39 self._password = password
40 self._tracker_source = tracker_source
42 # This will be initted on first login...
43 self._tracker_client = None
46 """Login, if needed. This may be safely called more than once.
48 Commands will call this function as their first line, so the client
49 of this class need not call it themselves unless trying to debug login
52 This function should be called even if we're accessing anonymously.
54 # Bail immediately if we've already logged in...
55 if self._tracker_client is not None:
58 self._tracker_client = gdata.projecthosting.client.ProjectHostingClient()
59 if self._email and self._password:
60 self._tracker_client.client_login(self._email, self._password,
61 source=self._tracker_source,
62 service="code", account_type='GOOGLE')
64 def GetKeyedLabels(self, project_name, issue_id):
65 """Get labels of the form "Key-Value" attached to the given issue.
67 Any labels that don't have a dash in them are ignored.
70 project_name: The tracker project to query.
71 issue_id: The ID of the issue to query; should be an int but a string
72 will probably work too.
75 A dictionary mapping key/value pairs from the issue's labels, like:
86 # Construct the query...
87 query = gdata.projecthosting.client.Query(issue_id=issue_id)
89 feed = self._tracker_client.get_issues(project_name, query=query)
90 except gdata.client.RequestError as e:
92 print("ERROR: Unable to access bug %s:%s: %s" %
93 (project_name, issue_id, str(e)), file=sys.stderr)
96 # There should be exactly one result...
97 assert len(feed.entry) == 1, "Expected exactly 1 result"
100 # We only care about labels that look like: Key-Value
101 # We'll return a dictionary of those.
103 for label in entry.label:
104 if "-" in label.text:
105 label_key, label_val = label.text.split("-", 1)
106 keyed_labels[label_key] = label_val
111 def _TestGetKeyedLabels(project_name, email, passwordFile, *args):
112 """Test code for GetKeyedLabels().
115 project_name: The name of the project we're looking at.
116 email: The email address to use to login. May be ""
117 passwordFile: A file containing the password for the email address.
118 May be "" if email is "" for anon access.
119 args: A list of bug IDs to query.
122 # If password was specified as a file, read it.
124 password = open(passwordFile, "r").read().strip()
128 ta = TrackerAccess(email, password)
131 print("No bugs were specified")
133 for bug_id in bug_ids:
134 print(bug_id, ta.GetKeyedLabels(project_name, int(bug_id)))
137 def _DoHelp(commands, *args):
138 """Print help for the script."""
140 if len(args) >= 2 and args[0] == "help" and args[1] in commands:
141 # If called with arguments 'help' and 'command', show that commands's doc.
142 command_name = args[1]
143 print(commands[command_name].__doc__)
145 # Something else: show generic help...
147 "Usage %s <command> <command args>\n"
151 % (sys.argv[0], pprint.pformat(["help"] + sorted(commands))))
155 """Main function of the script."""
158 "TestGetKeyedLabels": _TestGetKeyedLabels,
161 if len(sys.argv) <= 1 or sys.argv[1] not in commands:
162 # Argument 1 isn't in list of commands; show help and pass all arguments...
163 _DoHelp(commands, *sys.argv[1:])
165 command_name = sys.argv[1]
166 commands[command_name](*sys.argv[2:])
168 if __name__ == "__main__":