| Index: reviewbot/rietveld.py
|
| ===================================================================
|
| --- reviewbot/rietveld.py (revision 0)
|
| +++ reviewbot/rietveld.py (revision 0)
|
| @@ -0,0 +1,90 @@
|
| +# Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +from oauth2client.client import SignedJwtAssertionCredentials
|
| +import httplib2
|
| +import model.app_config
|
| +import urllib
|
| +import util
|
| +
|
| +
|
| +EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
|
| +
|
| +
|
| +class RietveldRequestError(Exception):
|
| + """Raised on request errors."""
|
| + pass
|
| +
|
| +
|
| +class Rietveld(object):
|
| + """Implements a Python API to access rietveld via HTTP.
|
| +
|
| + Authentication is handled via an OAuth2 access token minted from an RSA key
|
| + associated with a service account (which can be created via the Google API
|
| + console). For this to work, the Rietveld instance to talk to must be
|
| + configured to allow the service account client ID as OAuth2 audience (see
|
| + Rietveld source). Both the RSA key and the server URL are provided via static
|
| + application configuration.
|
| + """
|
| +
|
| + def __init__(self):
|
| + self.app_config = model.app_config.get()
|
| +
|
| + @util.lazy_property
|
| + def http(self):
|
| + http = httplib2.Http()
|
| +
|
| + creds = SignedJwtAssertionCredentials(self.app_config.client_id,
|
| + self.app_config.service_account_key,
|
| + EMAIL_SCOPE)
|
| + creds.authorize(http)
|
| + return http
|
| +
|
| + @util.lazy_property
|
| + def xsrf_token(self):
|
| + return self.make_request('xsrf_token',
|
| + headers={'X-Requesting-XSRF-Token': 1})
|
| +
|
| + def make_request(self, req, *args, **kwargs):
|
| + resp, response = self.http.request(
|
| + '%s/%s' % (self.app_config.server_url, req), *args, **kwargs)
|
| + if resp.status != 200:
|
| + raise RietveldRequestError(
|
| + 'Rietveld %s request failed: %s\n%s' %
|
| + (req, resp.status, str(resp)), resp, response)
|
| +
|
| + return response
|
| +
|
| + def post_data(self, req, payload=None):
|
| + actual_payload = dict(payload or {})
|
| + actual_payload['xsrf_token'] = self.xsrf_token
|
| +
|
| + return self.make_request(req, method='POST',
|
| + body=urllib.urlencode(actual_payload))
|
| +
|
| + def post_issue_data(self, issue, req, payload):
|
| + return self.post_data('%s/%s' % (issue, req), payload)
|
| +
|
| + def post_comment(self, issue, comment, submit_inline_comments=False):
|
| + publish_payload = {
|
| + 'message_only': 0 if submit_inline_comments else 1,
|
| + 'send_mail': 1,
|
| + 'add_as_reviewer': 0,
|
| + 'message': comment,
|
| + 'no_redirect': 1,
|
| + }
|
| + self.post_issue_data(issue, 'publish', publish_payload)
|
| +
|
| + def add_inline_comment(self, issue_id, patchset_id, patch_id, line, a_or_b,
|
| + comment):
|
| + comment_payload = {
|
| + 'snapshot': 'old' if a_or_b is 'a' else 'new',
|
| + 'lineno': line,
|
| + 'side': a_or_b,
|
| + 'issue': issue_id,
|
| + 'patchset': patchset_id,
|
| + 'patch': patch_id,
|
| + 'text': comment,
|
| + }
|
| + self.post_data('inline_draft', comment_payload)
|
|
|
| Property changes on: reviewbot/rietveld.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|