OLD | NEW |
(Empty) | |
| 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 """Utility functions to query the chromium issue tracker. |
| 6 |
| 7 Note that documentation for the Issue Tracker API says it's DEPRECATED, however |
| 8 it seems to be in use in other places like the performance dashboard. Also, |
| 9 this module attempts to handle most exceptions thrown by querying the tracker |
| 10 so that when and if this api is turned off no impact is caused to the bisection |
| 11 process.""" |
| 12 |
| 13 import json |
| 14 import urllib2 |
| 15 |
| 16 SINGLE_ISSUE_URL = ('https://code.google.com/feeds/issues/p/chromium/issues' |
| 17 '/full?id=%s&alt=json') |
| 18 |
| 19 |
| 20 class IssueTrackerQueryException(Exception): |
| 21 pass |
| 22 |
| 23 |
| 24 def QuerySingleIssue(issue_id, url_template=SINGLE_ISSUE_URL): |
| 25 """Queries the tracker for a specific issue. Returns a dict. |
| 26 |
| 27 This uses the deprecated Issue Tracker API to fetch a JSON representation of |
| 28 the issue details. |
| 29 |
| 30 Args: |
| 31 issue_id: An int or string representing the issue id. |
| 32 url_template: URL to query the tracker with '%s' instead of the bug id. |
| 33 |
| 34 Returns: |
| 35 A dictionary as parsed by the JSON library from the tracker response. |
| 36 |
| 37 Raises: |
| 38 urllib2.HTTPError when appropriate. |
| 39 """ |
| 40 assert str(issue_id).isdigit() |
| 41 response = urllib2.urlopen(url_template % issue_id).read() |
| 42 return json.loads(response) |
| 43 |
| 44 |
| 45 def GetIssueState(issue_id): |
| 46 """Returns either 'closed' or 'open' for the given bug ID. |
| 47 |
| 48 Args: |
| 49 issue_id: string or string-castable object containing a numeric bug ID. |
| 50 Returns: |
| 51 'open' or 'closed' depending on the state of the bug. |
| 52 Raises: |
| 53 IssueTrackerQueryException if the data cannot be retrieved or parsed. |
| 54 """ |
| 55 try: |
| 56 query_response = QuerySingleIssue(issue_id) |
| 57 # We assume the query returns a single result hence the [0] |
| 58 issue_detail = query_response['feed']['entry'][0] |
| 59 state = issue_detail['issues$state']['$t'] |
| 60 return state |
| 61 except urllib2.URLError: |
| 62 raise IssueTrackerQueryException( |
| 63 'Could not fetch the details form the issue tracker.') |
| 64 except ValueError: |
| 65 raise IssueTrackerQueryException( |
| 66 'Could not parse the issue tracker\'s response as a json doc.') |
| 67 except KeyError: |
| 68 raise IssueTrackerQueryException( |
| 69 'The data from the issue tracker is not in the expected format.') |
| 70 |
| 71 |
| 72 def CheckIssueClosed(issue_id): |
| 73 """Checks if a given issue is closed. Returns False when in doubt.""" |
| 74 try: |
| 75 return GetIssueState(issue_id) == 'closed' |
| 76 except IssueTrackerQueryException: |
| 77 # When we can't be sure we return false |
| 78 return False |
OLD | NEW |