moira-client

Форк
0
171 строка · 4.7 Кб
1
from retry.api import retry_call
2
from requests import HTTPError
3
from requests.auth import HTTPBasicAuth
4
import requests
5

6

7
def raise_for_status_with_body(r):
8
    try:
9
        r.raise_for_status()
10
    except HTTPError as e:
11
        try:
12
            body = r.json()
13
        except ValueError:
14
            body = r.text
15
        e.args = e.args + (body,)
16
        raise e
17

18

19
class ResponseStructureError(Exception):
20
    def __init__(self, msg, content):
21
        """
22

23
        :param msg: str error message
24
        :param content: dict response content
25
        """
26
        self.msg = msg
27
        self.content = content
28

29

30
class InvalidJSONError(Exception):
31
    def __init__(self, content):
32
        """
33

34
        :param content: bytes response content
35
        """
36
        self.content = content
37

38

39
class RetryPolicy:
40
    def __init__(self, max_tries=1, delay=0, backoff=1):
41
        """A helper object describing client retry policy.
42

43
        :param max_tries: maximum number of attempts
44
        :param delay: delay between attempts in seconds
45
        :param backoff: multiplier applied to delay between attempts
46
        """
47
        self.max_tries = max_tries
48
        self.delay = delay
49
        self.backoff = backoff
50

51
    def _as_kwargs(self):
52
        return {
53
            "tries": self.max_tries,
54
            "delay": self.delay,
55
            "backoff": self.backoff,
56
        }
57

58

59
class Client:
60
    def __init__(self, api_url, auth_custom=None, auth_user=None, auth_pass=None, login=None, retry_policy=None):
61
        """
62

63
        :param api_url: str Moira API URL
64
        :param auth_custom: dict auth custom headers
65
        :param auth_user: str auth user
66
        :param auth_pass: str auth password
67
        :param login: str auth login
68
        :param retry_policy: RetryPolicy
69
        """
70
        if not api_url.endswith('/'):
71
            self.api_url = api_url + '/'
72
        else:
73
            self.api_url = api_url
74

75
        self.retry_policy = retry_policy or RetryPolicy()
76

77
        self.auth = None
78
        self.headers = {
79
            'X-Webauth-User': login,
80
            'Content-Type': 'application/json',
81
            'User-Agent': 'Python Moira Client'
82
            }
83

84
        if auth_user and auth_pass:
85
            self.auth = HTTPBasicAuth(auth_user, auth_pass)
86

87
        if auth_custom:
88
            self.headers.update(auth_custom)
89

90
    def get(self, path='', **kwargs):
91
        """
92

93
        :param path: str api path
94
        :param kwargs: additional parameters for request
95
        :return: dict response
96

97
        :raises: HTTPError
98
        :raises: InvalidJSONError
99
        """
100
        return retry_call(
101
            self._get, (path, ), kwargs,
102
            **self.retry_policy._as_kwargs(),
103
        )
104

105
    def _get(self, path='', **kwargs):
106
        r = requests.get(self._path_join(path), timeout=10, headers=self.headers, auth=self.auth, **kwargs)
107
        raise_for_status_with_body(r)
108
        try:
109
            return r.json()
110
        except ValueError:
111
            raise InvalidJSONError(r.content)
112

113
    def delete(self, path='', **kwargs):
114
        """
115

116
        :param path: str api path
117
        :param kwargs: additional parameters for request
118
        :return: dict response
119

120
        :raises: HTTPError
121
        :raises: InvalidJSONError
122
        """
123
        return retry_call(
124
            self._delete, (path, ), kwargs,
125
            **self.retry_policy._as_kwargs(),
126
        )
127

128
    def _delete(self, path='', **kwargs):
129
        r = requests.delete(self._path_join(path), timeout=10, headers=self.headers, auth=self.auth, **kwargs)
130
        raise_for_status_with_body(r)
131
        # AD-13298: DELETE requests (sometimes?) return a 0-byte response
132
        # and this is not an error
133
        if len(r.content) == 0:
134
            return None
135
        else:
136
            try:
137
                return r.json()
138
            except ValueError:
139
                raise InvalidJSONError(r.content)
140

141
    def put(self, path='', **kwargs):
142
        """
143

144
        :param path: str api path
145
        :param kwargs: additional parameters for request
146
        :return: dict response
147

148
        :raises: HTTPError
149
        :raises: InvalidJSONError
150
        """
151
        return retry_call(
152
            self._put, (path, ), kwargs,
153
            **self.retry_policy._as_kwargs(),
154
        )
155

156
    def _put(self, path='', **kwargs):
157
        r = requests.put(self._path_join(path), timeout=10, headers=self.headers, auth=self.auth, **kwargs)
158
        raise_for_status_with_body(r)
159
        try:
160
            return r.json()
161
        except ValueError:
162
            raise InvalidJSONError(r.content)
163

164
    def _path_join(self, *args):
165
        path = self.api_url
166
        for part in args:
167
            if part.startswith('/'):
168
                path += part[1:]
169
            else:
170
                path += part
171
        return path
172

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.