comparison planemo/lib/python3.7/site-packages/bioblend/galaxyclient.py @ 0:d30785e31577 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:18:57 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d30785e31577
1 """
2 Helper class for Galaxy and ToolShed Instance object
3
4 This class is primarily a helper for the library and user code
5 should not use it directly.
6 A base representation of an instance
7 """
8 import base64
9 import json
10 from urllib.parse import (
11 urljoin,
12 urlparse,
13 )
14
15 import requests
16 from requests_toolbelt import MultipartEncoder
17
18 from bioblend import ConnectionError
19 from bioblend.util import FileStream
20
21
22 class GalaxyClient(object):
23
24 def __init__(self, url, key=None, email=None, password=None, verify=True, timeout=None):
25 """
26 :param verify: Whether to verify the server's TLS certificate
27 :type verify: bool
28 :param timeout: Timeout for requests operations, set to None for no timeout (the default).
29 :type timeout: float
30 """
31 # Make sure the url scheme is defined (otherwise requests will not work)
32 if not urlparse(url).scheme:
33 url = "http://" + url
34 # All of Galaxy's and ToolShed's API's are rooted at <url>/api so make that the url
35 self.base_url = url
36 self.url = urljoin(url, 'api')
37 # If key has been supplied, use it; otherwise just set email and
38 # password and grab user's key before first request.
39 if key:
40 self._key = key
41 else:
42 self._key = None
43 self.email = email
44 self.password = password
45 self.json_headers = {'Content-Type': 'application/json'}
46 self.verify = verify
47 self.timeout = timeout
48
49 def make_get_request(self, url, **kwargs):
50 """
51 Make a GET request using the provided ``url``.
52
53 Keyword arguments are the same as in requests.request.
54
55 If ``verify`` is not provided, ``self.verify`` will be used.
56
57 If the ``params`` are not provided, use ``default_params`` class field.
58 If params are provided and the provided dict does not have ``key`` key,
59 the default ``self.key`` value will be included in what's passed to
60 the server via the request.
61
62 :rtype: requests.Response
63 :return: the response object.
64 """
65 params = kwargs.get('params')
66 if params is not None and params.get('key', False) is False:
67 params['key'] = self.key
68 else:
69 params = self.default_params
70 kwargs['params'] = params
71 kwargs.setdefault('verify', self.verify)
72 kwargs.setdefault('timeout', self.timeout)
73 r = requests.get(url, **kwargs)
74 return r
75
76 def make_post_request(self, url, payload, params=None, files_attached=False):
77 """
78 Make a POST request using the provided ``url`` and ``payload``.
79 The ``payload`` must be a dict that contains the request values.
80 The payload dict may contain file handles (in which case the files_attached
81 flag must be set to true).
82
83 If the ``params`` are not provided, use ``default_params`` class field.
84 If params are provided and the provided dict does not have ``key`` key,
85 the default ``self.key`` value will be included in what's passed to
86 the server via the request.
87
88 :return: The decoded response.
89 """
90
91 def my_dumps(d):
92 """
93 Apply ``json.dumps()`` to the values of the dict ``d`` if they are
94 not of type ``FileStream``.
95 """
96 for k, v in d.items():
97 if not isinstance(v, FileStream):
98 d[k] = json.dumps(v)
99 return d
100
101 if params is not None and params.get('key', False) is False:
102 params['key'] = self.key
103 else:
104 params = self.default_params
105
106 # Compute data, headers, params arguments for request.post,
107 # leveraging the requests-toolbelt library if any files have
108 # been attached.
109 if files_attached:
110 payload = my_dumps(payload)
111 payload.update(params)
112 payload = MultipartEncoder(fields=payload)
113 headers = self.json_headers.copy()
114 headers['Content-Type'] = payload.content_type
115 post_params = {}
116 else:
117 payload = json.dumps(payload)
118 headers = self.json_headers
119 post_params = params
120
121 r = requests.post(url, data=payload, headers=headers,
122 verify=self.verify, params=post_params,
123 timeout=self.timeout)
124 if r.status_code == 200:
125 try:
126 return r.json()
127 except Exception as e:
128 raise ConnectionError("Request was successful, but cannot decode the response content: %s" %
129 e, body=r.content, status_code=r.status_code)
130 # @see self.body for HTTP response body
131 raise ConnectionError("Unexpected HTTP status code: %s" % r.status_code,
132 body=r.text, status_code=r.status_code)
133
134 def make_delete_request(self, url, payload=None, params=None):
135 """
136 Make a DELETE request using the provided ``url`` and the optional
137 arguments.
138
139 If the ``params`` are not provided, use ``default_params`` class field.
140 If params are provided and the provided dict does not have ``key`` key,
141 the default ``self.key`` value will be included in what's passed to
142 the server via the request.
143
144 :type payload: dict
145 :param payload: a JSON-serializable dictionary
146
147 :rtype: requests.Response
148 :return: the response object.
149 """
150 if params is not None and params.get('key', False) is False:
151 params['key'] = self.key
152 else:
153 params = self.default_params
154 if payload is not None:
155 payload = json.dumps(payload)
156 headers = self.json_headers
157 r = requests.delete(url, verify=self.verify, data=payload, params=params,
158 headers=headers, timeout=self.timeout)
159 return r
160
161 def make_put_request(self, url, payload=None, params=None):
162 """
163 Make a PUT request using the provided ``url`` with required payload.
164
165 :type payload: dict
166 :param payload: a JSON-serializable dictionary
167
168 :return: The decoded response.
169 """
170 if params is not None and params.get('key', False) is False:
171 params['key'] = self.key
172 else:
173 params = self.default_params
174
175 payload = json.dumps(payload)
176 headers = self.json_headers
177 r = requests.put(url, data=payload, params=params, headers=headers,
178 verify=self.verify, timeout=self.timeout)
179 if r.status_code == 200:
180 try:
181 return r.json()
182 except Exception as e:
183 raise ConnectionError("Request was successful, but cannot decode the response content: %s" %
184 e, body=r.content, status_code=r.status_code)
185 # @see self.body for HTTP response body
186 raise ConnectionError("Unexpected HTTP status code: %s" % r.status_code,
187 body=r.text, status_code=r.status_code)
188
189 def make_patch_request(self, url, payload=None, params=None):
190 """
191 Make a PATCH request using the provided ``url`` with required payload.
192
193 :type payload: dict
194 :param payload: a JSON-serializable dictionary
195
196 :return: The decoded response.
197 """
198 if params is not None and params.get('key', False) is False:
199 params['key'] = self.key
200 else:
201 params = self.default_params
202
203 payload = json.dumps(payload)
204 headers = self.json_headers
205 r = requests.patch(url, data=payload, params=params, headers=headers,
206 verify=self.verify, timeout=self.timeout)
207 if r.status_code == 200:
208 try:
209 return r.json()
210 except Exception as e:
211 raise ConnectionError("Request was successful, but cannot decode the response content: %s" %
212 e, body=r.content, status_code=r.status_code)
213 # @see self.body for HTTP response body
214 raise ConnectionError("Unexpected HTTP status code: %s" % r.status_code,
215 body=r.text, status_code=r.status_code)
216
217 @property
218 def key(self):
219 if not self._key and self.email is not None and self.password is not None:
220 unencoded_credentials = "%s:%s" % (self.email, self.password)
221 authorization = base64.b64encode(unencoded_credentials.encode())
222 headers = self.json_headers.copy()
223 headers["Authorization"] = authorization
224 auth_url = "%s/authenticate/baseauth" % self.url
225 # make_post_request uses default_params, which uses this and
226 # sets wrong headers - so using lower level method.
227 r = requests.get(auth_url, verify=self.verify, headers=headers)
228 if r.status_code != 200:
229 raise Exception("Failed to authenticate user.")
230 response = r.json()
231 if isinstance(response, str):
232 # bug in Tool Shed
233 response = json.loads(response)
234 self._key = response["api_key"]
235 return self._key
236
237 @property
238 def default_params(self):
239 return {'key': self.key}