| OLD | NEW |
| 1 """Provides API wrapper for the codesite issue tracker""" | 1 """Provides API wrapper for the codesite issue tracker""" |
| 2 | 2 |
| 3 import httplib2 | 3 import httplib2 |
| 4 import logging | 4 import logging |
| 5 import time | 5 import time |
| 6 | 6 |
| 7 from apiclient import discovery | 7 from apiclient import discovery |
| 8 from apiclient.errors import HttpError | 8 from apiclient.errors import HttpError |
| 9 from issue_tracker.issue import Issue | 9 from issue_tracker.issue import Issue |
| 10 from issue_tracker.comment import Comment | 10 from issue_tracker.comment import Comment |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 'apiclient.discovery.build() failed for %s too many times.', | 45 'apiclient.discovery.build() failed for %s too many times.', |
| 46 api_name) | 46 api_name) |
| 47 raise e | 47 raise e |
| 48 return client | 48 return client |
| 49 | 49 |
| 50 | 50 |
| 51 class IssueTrackerAPI(object): # pragma: no cover | 51 class IssueTrackerAPI(object): # pragma: no cover |
| 52 CAN_ALL = 'all' | 52 CAN_ALL = 'all' |
| 53 | 53 |
| 54 """A wrapper around the issue tracker api.""" | 54 """A wrapper around the issue tracker api.""" |
| 55 def __init__(self, project_name, use_monorail): | 55 def __init__(self, project_name): |
| 56 self.project_name = project_name | 56 self.project_name = project_name |
| 57 self.use_monorail = use_monorail | |
| 58 | 57 |
| 59 if use_monorail: | 58 self.client = _buildClient( |
| 60 self.client = _buildClient( | 59 'monorail', 'v1', |
| 61 'monorail', 'v1', | 60 _createHttpObject('https://www.googleapis.com/auth/userinfo.email'), |
| 62 _createHttpObject('https://www.googleapis.com/auth/userinfo.email'), | 61 'https://monorail-prod.appspot.com/_ah/api/discovery/v1/apis/{api}/' |
| 63 'https://monorail-prod.appspot.com/_ah/api/discovery/v1/apis/{api}/' | 62 '{apiVersion}/rest') |
| 64 '{apiVersion}/rest') | |
| 65 else: | |
| 66 self.client = _buildClient( | |
| 67 'projecthosting', 'v2', | |
| 68 _createHttpObject('https://www.googleapis.com/auth/projecthosting'), | |
| 69 'https://www.googleapis.com/discovery/v1/apis/{api}/{apiVersion}/' | |
| 70 'rest') | |
| 71 | 63 |
| 72 def _retry_api_call(self, request, num_retries=5): | 64 def _retry_api_call(self, request, num_retries=5): |
| 73 retries = 0 | 65 retries = 0 |
| 74 while True: | 66 while True: |
| 75 try: | 67 try: |
| 76 return request.execute() | 68 return request.execute() |
| 77 except HttpError as e: | 69 except HttpError as e: |
| 78 # This retries internal server (500, 503) and quota (403) errors. | 70 # This retries internal server (500, 503) and quota (403) errors. |
| 79 if retries == num_retries or e.resp.status not in [403, 500, 503]: | 71 if retries == num_retries or e.resp.status not in [403, 500, 503]: |
| 80 raise | 72 raise |
| (...skipping 26 matching lines...) Expand all Loading... |
| 107 def update(self, issue, comment=None, send_email=True): | 99 def update(self, issue, comment=None, send_email=True): |
| 108 if not issue.dirty and not comment: | 100 if not issue.dirty and not comment: |
| 109 return issue | 101 return issue |
| 110 | 102 |
| 111 updates = {} | 103 updates = {} |
| 112 if 'summary' in issue.changed: | 104 if 'summary' in issue.changed: |
| 113 updates['summary'] = issue.summary | 105 updates['summary'] = issue.summary |
| 114 if 'status' in issue.changed: | 106 if 'status' in issue.changed: |
| 115 updates['status'] = issue.status | 107 updates['status'] = issue.status |
| 116 if 'owner' in issue.changed: | 108 if 'owner' in issue.changed: |
| 117 # workaround for existing bug: | 109 updates['owner'] = issue.owner |
| 118 # https://code.google.com/a/google.com/p/codesite/issues/detail?id=115 | |
| 119 if self.use_monorail: | |
| 120 updates['owner'] = issue.owner | |
| 121 else: | |
| 122 updates['owner'] = issue.owner if issue.owner else '----' | |
| 123 if 'blocked_on' in issue.changed: | 110 if 'blocked_on' in issue.changed: |
| 124 updates['blockedOn'] = issue.blocked_on | 111 updates['blockedOn'] = issue.blocked_on |
| 125 if issue.labels.isChanged(): | 112 if issue.labels.isChanged(): |
| 126 updates['labels'] = list(issue.labels.added) | 113 updates['labels'] = list(issue.labels.added) |
| 127 updates['labels'].extend('-%s' % label for label in issue.labels.removed) | 114 updates['labels'].extend('-%s' % label for label in issue.labels.removed) |
| 128 if issue.components.isChanged(): | 115 if issue.components.isChanged(): |
| 129 updates['components'] = list(issue.components.added) | 116 updates['components'] = list(issue.components.added) |
| 130 updates['components'].extend( | 117 updates['components'].extend( |
| 131 '-%s' % comp for comp in issue.components.removed) | 118 '-%s' % comp for comp in issue.components.removed) |
| 132 if issue.cc.isChanged(): | 119 if issue.cc.isChanged(): |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 if 'items' in feed and len(feed['items']) > 0: | 185 if 'items' in feed and len(feed['items']) > 0: |
| 199 return Comment(feed['items'][0]) | 186 return Comment(feed['items'][0]) |
| 200 return None | 187 return None |
| 201 | 188 |
| 202 def getIssue(self, issue_id): | 189 def getIssue(self, issue_id): |
| 203 """Retrieve a set of issues in a project.""" | 190 """Retrieve a set of issues in a project.""" |
| 204 request = self.client.issues().get( | 191 request = self.client.issues().get( |
| 205 projectId=self.project_name, issueId=issue_id) | 192 projectId=self.project_name, issueId=issue_id) |
| 206 entry = self._retry_api_call(request) | 193 entry = self._retry_api_call(request) |
| 207 return Issue(entry) | 194 return Issue(entry) |
| OLD | NEW |