From c8827d1fd8ba4cf232946e81c5a761a41c9f7313 Mon Sep 17 00:00:00 2001 From: Yo Chiang Date: Mon, 20 Apr 2020 16:51:34 +0800 Subject: [PATCH 1/2] repo_review: Add --add-reviewer, --delete-reviewer Test: ./repo_review.py --add-reviewer [lint bot] [query] Test: ./repo_review.py --delete-reviewer [lint bot] [query] Change-Id: I2c9001ef83e48656053db1dbfe7d373ce2b26eea --- tools/repo_pull/gerrit.py | 25 +++++++++++++++++++++++++ tools/repo_pull/repo_review.py | 24 ++++++++++++++++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/tools/repo_pull/gerrit.py b/tools/repo_pull/gerrit.py index 063b35105..eab28bd39 100755 --- a/tools/repo_pull/gerrit.py +++ b/tools/repo_pull/gerrit.py @@ -149,6 +149,9 @@ def _make_json_post_request(url_opener, url, data, method='POST'): response_file = url_opener.open(request) try: res_code = response_file.getcode() + # Nothing to parse if response is '204 No Content' + if res_code == 204: + return (res_code, None) res_json = _decode_xssi_json(response_file.read()) return (res_code, res_json) finally: @@ -231,6 +234,28 @@ def get_patch(url_opener, gerrit_url, change_id, revision_id='current'): response_file.close() +def add_reviewers(url_opener, gerrit_url, change_id, reviewers): + """Add reviewers.""" + + url = '{}/a/changes/{}/revisions/current/review'.format( + gerrit_url, change_id) + + data = {} + if reviewers: + data['reviewers'] = reviewers + + return _make_json_post_request(url_opener, url, data) + + +def delete_reviewer(url_opener, gerrit_url, change_id, name): + """Delete reviewer.""" + + url = '{}/a/changes/{}/reviewers/{}/delete'.format( + gerrit_url, change_id, name) + + return _make_json_post_request(url_opener, url, {}) + + def _parse_args(): """Parse command line options.""" parser = argparse.ArgumentParser() diff --git a/tools/repo_pull/repo_review.py b/tools/repo_pull/repo_review.py index 2279e4b1c..743505b04 100755 --- a/tools/repo_pull/repo_review.py +++ b/tools/repo_pull/repo_review.py @@ -31,8 +31,8 @@ except ImportError: from urllib2 import HTTPError # PY2 from gerrit import ( - abandon, create_url_opener_from_args, delete_topic, query_change_lists, - set_hashtags, set_review, set_topic) + add_reviewers, delete_reviewer, abandon, create_url_opener_from_args, + delete_topic, query_change_lists, set_hashtags, set_review, set_topic) def _get_labels_from_args(args): @@ -112,6 +112,10 @@ def _parse_args(): help='Delete topic name') parser.add_argument('--remove-topic', action='store_true', help='Delete topic name', dest='delete_topic') + parser.add_argument('--add-reviewer', action='append', default=[], + help='Add reviewer') + parser.add_argument('--delete-reviewer', action='append', default=[], + help='Delete reviewer') return parser.parse_args() @@ -126,6 +130,8 @@ def _has_task(args): return True if args.set_topic or args.delete_topic: return True + if args.add_reviewer or args.delete_reviewer: + return True return False @@ -178,13 +184,16 @@ def main(): args = _parse_args() if not _has_task(args): print('error: Either --label, --message, --abandon, --add-hashtag, ' - '--remove-hashtag, --set-topic, or --delete-topic must be ', - 'specified', file=sys.stderr) + '--remove-hashtag, --set-topic, --delete-topic, --add-reviewer ' + 'or --delete-reviewer must be specified', file=sys.stderr) sys.exit(1) # Convert label arguments labels = _get_labels_from_args(args) + # Convert reviewer arguments + new_reviewers = [{'reviewer': name} for name in args.add_reviewer] + # Load authentication credentials url_opener = create_url_opener_from_args(args) @@ -220,6 +229,13 @@ def main(): if args.abandon: _do_task(change, abandon, url_opener, args.gerrit, change['id'], args.abandon, errors=errors) + if args.add_reviewer: + _do_task(change, add_reviewers, url_opener, args.gerrit, + change['id'], new_reviewers, errors=errors) + for name in args.delete_reviewer: + _do_task(change, delete_reviewer, url_opener, args.gerrit, + change['id'], name, expected_http_code=204, errors=errors) + if errors['num_errors']: sys.exit(1) From dc9a2b7ec91aa1adf7b59217106fe6ce45f2eb4c Mon Sep 17 00:00:00 2001 From: Yo Chiang Date: Mon, 20 Apr 2020 17:59:23 +0800 Subject: [PATCH 2/2] repo_pull: Handle abnormal responses urllib.error.HTTPError works as a http response object (same type that urlopen() returns). Handle the exception by reading and parsing the response body of the error. Test: ./repo_review.py --add-reviewer [invalid username] [query] Test: ./repo_review.py --add-reviewer [ambiguous username] [query] Change-Id: Ibfc261d83f2f9efd7873835f74ce8d5e980821c9 --- tools/repo_pull/gerrit.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/repo_pull/gerrit.py b/tools/repo_pull/gerrit.py index eab28bd39..a4cd7dc36 100755 --- a/tools/repo_pull/gerrit.py +++ b/tools/repo_pull/gerrit.py @@ -26,6 +26,11 @@ import json import os import sys +try: + from urllib.error import HTTPError # PY3 +except ImportError: + from urllib2 import HTTPError # PY2 + try: from urllib.request import ( HTTPBasicAuthHandler, Request, build_opener) # PY3 @@ -146,16 +151,19 @@ def _make_json_post_request(url_opener, url, data, method='POST'): request = Request(url, data, headers) request.get_method = lambda: method - response_file = url_opener.open(request) + try: + response_file = url_opener.open(request) + except HTTPError as error: + response_file = error + + with response_file: res_code = response_file.getcode() # Nothing to parse if response is '204 No Content' if res_code == 204: return (res_code, None) res_json = _decode_xssi_json(response_file.read()) return (res_code, res_json) - finally: - response_file.close() def set_review(url_opener, gerrit_url, change_id, labels, message):