comparison venv/lib/python2.7/site-packages/bioblend/galaxyclient.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
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
11 import requests
12 from requests_toolbelt import MultipartEncoder
13 import six
14 from six.moves.urllib.parse import urljoin, urlparse
15
16 from .galaxy.client import ConnectionError
17
18
19 class GalaxyClient(object):
20
21 def __init__(self, url, key=None, email=None, password=None):
22 # Make sure the url scheme is defined (otherwise requests will not work)
23 if not urlparse(url).scheme:
24 url = "http://" + url
25 # All of Galaxy's and ToolShed's API's are rooted at <url>/api so make that the url
26 self.base_url = url
27 self.url = urljoin(url, 'api')
28 # If key has been supplied, use it; otherwise just set email and
29 # password and grab user's key before first request.
30 if key:
31 self._key = key
32 else:
33 self._key = None
34 self.email = email
35 self.password = password
36 self.json_headers = {'Content-Type': 'application/json'}
37 self.verify = True # Should SSL verification be done
38
39 def _make_url(self, module, module_id=None, deleted=False, contents=False):
40 """
41 Compose a URL based on the provided arguments.
42
43 :type module: :class:`~.galaxy.Client` subclass
44 :param module: The base module for which to make the URL. For
45 example: an object of class LibraryClient, WorkflowClient,
46 HistoryClient, ToolShedClient
47
48 :type module_id: str
49 :param module_id: The encoded ID for a specific module (eg, library ID)
50
51 :type deleted: bool
52 :param deleted: If ``True``, include ``deleted`` in the URL, after the module
53 name (eg, ``<base_url>/api/libraries/deleted``)
54
55 :type contents: bool
56 :param contents: If ``True``, include 'contents' in the URL, after the module ID:
57 ``<base_url>/api/libraries/<encoded_library_id>/contents``
58 """
59 c_url = self.url
60 c_url = '/'.join([c_url, module.module])
61 if deleted is True:
62 c_url = '/'.join([c_url, 'deleted'])
63 if module_id is not None:
64 c_url = '/'.join([c_url, module_id])
65 if contents is True:
66 c_url = '/'.join([c_url, 'contents'])
67 return c_url
68
69 def make_get_request(self, url, **kwargs):
70 """
71 Make a GET request using the provided ``url``.
72
73 Keyword arguments are the same as in requests.request.
74
75 If ``verify`` is not provided, ``self.verify`` will be used.
76
77 If the ``params`` are not provided, use ``default_params`` class field.
78 If params are provided and the provided dict does not have ``key`` key,
79 the default ``self.key`` value will be included in what's passed to
80 the server via the request.
81 """
82 params = kwargs.get('params')
83 if params is not None and params.get('key', False) is False:
84 params['key'] = self.key
85 else:
86 params = self.default_params
87 kwargs['params'] = params
88 kwargs.setdefault('verify', self.verify)
89 r = requests.get(url, **kwargs)
90 return r
91
92 def make_post_request(self, url, payload, params=None, files_attached=False):
93 """
94 Make a POST request using the provided ``url`` and ``payload``.
95 The ``payload`` must be a dict that contains the request values.
96 The payload dict may contain file handles (in which case the files_attached
97 flag must be set to true).
98
99 If the ``params`` are not provided, use ``default_params`` class field.
100 If params are provided and the provided dict does not have ``key`` key,
101 the default ``self.key`` value will be included in what's passed to
102 the server via the request.
103
104 The return value will contain the response body as a JSON object.
105 """
106 if params is not None and params.get('key', False) is False:
107 params['key'] = self.key
108 else:
109 params = self.default_params
110
111 # Compute data, headers, params arguments for request.post,
112 # leveraging the requests-toolbelt library if any files have
113 # been attached.
114 if files_attached:
115 payload.update(params)
116 payload = MultipartEncoder(fields=payload)
117 headers = self.json_headers.copy()
118 headers['Content-Type'] = payload.content_type
119 post_params = {}
120 else:
121 payload = json.dumps(payload)
122 headers = self.json_headers
123 post_params = params
124
125 r = requests.post(url, data=payload, headers=headers,
126 verify=self.verify, params=post_params)
127 if r.status_code == 200:
128 return r.json()
129 # @see self.body for HTTP response body
130 raise ConnectionError("Unexpected response from galaxy: %s" %
131 r.status_code, body=r.text)
132
133 def make_delete_request(self, url, payload=None, params=None):
134 """
135 Make a DELETE request using the provided ``url`` and the optional
136 arguments.
137 The ``payload`` must be a dict that can be converted into a JSON
138 object (via ``json.dumps``)
139
140 If the ``params`` are not provided, use ``default_params`` class field.
141 If params are provided and the provided dict does not have ``key`` key,
142 the default ``self.key`` value will be included in what's passed to
143 the server via the request.
144 """
145 if params is not None and params.get('key', False) is False:
146 params['key'] = self.key
147 else:
148 params = self.default_params
149 r = requests.delete(url, verify=self.verify, data=payload, params=params)
150 return r
151
152 def make_put_request(self, url, payload=None, params=None):
153 """
154 Make a PUT request using the provided ``url`` with required payload.
155 The ``payload`` must be a dict that can be converted into a JSON
156 object (via ``json.dumps``)
157 """
158 if params is not None and params.get('key', False) is False:
159 params['key'] = self.key
160 else:
161 params = self.default_params
162
163 payload = json.dumps(payload)
164 r = requests.put(url, verify=self.verify, data=payload, params=params)
165 return r
166
167 @property
168 def key(self):
169 if not self._key and self.email is not None and self.password is not None:
170 unencoded_credentials = "%s:%s" % (self.email, self.password)
171 authorization = base64.b64encode(unencoded_credentials)
172 headers = self.json_headers.copy()
173 headers["Authorization"] = authorization
174 auth_url = "%s/authenticate/baseauth" % self.url
175 # make_post_request uses default_params, which uses this and
176 # sets wrong headers - so using lower level method.
177 r = requests.get(auth_url, verify=self.verify, headers=headers)
178 if r.status_code != 200:
179 raise Exception("Failed to authenticate user.")
180 response = r.json()
181 if isinstance(response, (six.string_types, six.text_type)):
182 # bug in Tool Shed
183 response = json.loads(response)
184 self._key = response["api_key"]
185 return self._key
186
187 @property
188 def default_params(self):
189 return {'key': self.key}