1 # Copyright (c) 2020 The Regents of the University of California
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met: redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer;
8 # redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution;
11 # neither the name of the copyright holders nor the names of its
12 # contributors may be used to endorse or promote products derived from
13 # this software without specific prior written permission.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 from types
import SimpleNamespace
31 from urllib
.parse
import urljoin
33 class GerritResponseParser
:
35 def get_json_content(response
):
36 assert(isinstance(response
, requests
.Response
))
38 # If the status code is not in the 200s range, it doesn't have content.
39 if response
.status_code
>= 300:
42 # Transform response.content to a Python3 string.
43 # response.content is a byte array containing the response.
44 # The first 4 bytes are b")]}\", which doesn't belong to JSON content.
45 # The byte array is encoded by utf-8.
46 content
= response
.content
[4:].decode("utf-8")
47 json_content
= json
.loads(content
)
50 # TODO: parsing method for each Gerrit data structure
53 json_content
= GerritResponseParser
.get_json_content(response
)
56 return SimpleNamespace(**json_content
)
60 def __init__(self
, auth
, api_entry_point
, timeout
):
61 self
.username
= auth
[0]
62 self
.password
= auth
[1]
63 self
.api_entry_point
= api_entry_point
64 self
.timeout
= timeout
66 # helper methods for sending GET and POST requests
67 def _get(self
, endpoint
, params
= None):
68 request_url
= urljoin(self
.api_entry_point
, endpoint
)
69 return requests
.get(request_url
,
71 timeout
= self
.timeout
,
72 auth
= (self
.username
, self
.password
))
73 def _post(self
, endpoint
, json_content
):
74 request_url
= urljoin(self
.api_entry_point
, endpoint
)
75 return requests
.post(request_url
,
77 timeout
= self
.timeout
,
78 auth
= (self
.username
, self
.password
))
80 # --------------- Account Endpoints ---------------
81 # https://gerrit-review.googlesource.com/Documentation/
82 # rest-api-accounts.html#get-account
83 def get_account(self
, account_id
="self"):
84 """ get an account detail from an account_id """
85 return self
._get
(f
"/accounts/{account_id}")
87 # https://gerrit-review.googlesource.com/Documentation/
88 # rest-api-accounts.html#query-account
89 def query_account(self
, query
, limit
= None):
90 """ get accounts based on the query """
91 params
= { "q": query
}
93 params
["n"] = str(limit
)
94 return self
._get
(f
"/accounts/", params
)
96 # --------------- Changes Endpoints ---------------
97 # https://gerrit-review.googlesource.com/Documentation/
98 # rest-api-changes.html#list-changes
99 def query_changes(self
, query
, limit
=None, optional_field
=None):
100 """ query changes with maximum limit returned queries """
101 endpoint
= f
"/changes/"
102 params
= { "q": query
}
104 params
["n"] = str(limit
)
106 params
["o"] = optional_field
107 return self
._get
(endpoint
, params
)
109 # --------------- Reviewer Endpoints ---------------
110 # https://gerrit-review.googlesource.com/Documentation/
111 # rest-api-changes.html#list-reviewers
112 def list_reviewers(self
, change_id
):
113 """ list reviewers of a change """
114 return self
._get
(f
"/changes/{change_id}/reviewers")
115 def add_reviewer(self
, change_id
, reviewer_email
):
116 """ add a reviewer using an email address """
117 data
= {"reviewer": reviewer_email
}
118 return self
._post
(f
"/changes/{change_id}/reviewers/", data
)