blob: 7ed5900aff0e4b788839de78794feb7a2319eb62 [file] [log] [blame]
Serhii Turivnyi9eccd842019-07-18 17:02:29 +03001#
2# TestRail API binding for Python 3.x (API v2, available since
3# TestRail 3.0)
4#
5# Learn more:
6#
7# http://docs.gurock.com/testrail-api2/start
8# http://docs.gurock.com/testrail-api2/accessing
9#
10# Copyright Gurock Software GmbH. See license.md for details.
11#
12
13import urllib.request, urllib.error
14import json, base64
15import time
16
17class APIClient:
18 def __init__(self, base_url):
19 self.user = ''
20 self.password = ''
21 if not base_url.endswith('/'):
22 base_url += '/'
23 self.__url = base_url + 'index.php?/api/v2/'
24
25 #
26 # Send Get
27 #
28 # Issues a GET request (read) against the API and returns the result
29 # (as Python dict).
30 #
31 # Arguments:
32 #
33 # uri The API method to call including parameters
34 # (e.g. get_case/1)
35 #
36 def send_get(self, uri):
37 try:
38 return self.__send_request('GET', uri, None)
39 except APIError:
40 print("Got an API Exception. Waiting 30 sec.")
41 time.sleep(30)
42 return self.__send_request('GET', uri, None)
43
44 #
45 # Send POST
46 #
47 # Issues a POST request (write) against the API and returns the result
48 # (as Python dict).
49 #
50 # Arguments:
51 #
52 # uri The API method to call including parameters
53 # (e.g. add_case/1)
54 # data The data to submit as part of the request (as
55 # Python dict, strings must be UTF-8 encoded)
56 #
57 def send_post(self, uri, data):
58 return self.__send_request('POST', uri, data)
59
60 def __send_request(self, method, uri, data):
61 url = self.__url + uri
62 request = urllib.request.Request(url)
63 if (method == 'POST'):
64 request.data = bytes(json.dumps(data), 'utf-8')
65 auth = str(
66 base64.b64encode(
67 bytes('%s:%s' % (self.user, self.password), 'utf-8')
68 ),
69 'ascii'
70 ).strip()
71 request.add_header('Authorization', 'Basic %s' % auth)
72 request.add_header('Content-Type', 'application/json')
73
74 e = None
75 try:
76 response = urllib.request.urlopen(request).read()
77 except urllib.error.HTTPError as ex:
78 response = ex.read()
79 e = ex
80
81 if response:
82 result = json.loads(response.decode())
83 else:
84 result = {}
85
86 if e != None:
87 if result and 'error' in result:
88 error = '"' + result['error'] + '"'
89 else:
90 error = 'No additional error message received'
91 raise APIError('TestRail API returned HTTP %s (%s)' %
92 (e.code, error))
93
94 return result
95
96class APIError(Exception):
97 pass