comparison venv/lib/python2.7/site-packages/bioblend/galaxy/objects/client.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 Clients for interacting with specific Galaxy entity types.
3
4 Classes in this module should not be instantiated directly, but used
5 via their handles in :class:`~.galaxy_instance.GalaxyInstance`.
6 """
7 import abc
8 import collections
9 import json
10
11 import six
12
13 import bioblend
14 from . import wrappers
15
16
17 @six.add_metaclass(abc.ABCMeta)
18 class ObjClient(object):
19
20 @abc.abstractmethod
21 def __init__(self, obj_gi):
22 self.obj_gi = obj_gi
23 self.gi = self.obj_gi.gi
24 self.log = bioblend.log
25
26 @abc.abstractmethod
27 def get_previews(self, **kwargs):
28 """
29 Get a list of object previews.
30
31 Previews entity summaries provided by REST collection URIs, e.g.
32 ``http://host:port/api/libraries``. Being the most lightweight objects
33 associated to the various entities, these are the ones that should be
34 used to retrieve their basic info.
35
36 :rtype: list
37 :return: a list of object previews
38 """
39 pass
40
41 @abc.abstractmethod
42 def list(self, **kwargs):
43 """
44 Get a list of objects.
45
46 This method first gets the entity summaries, then gets the complete
47 description for each entity with an additional GET call, so may be slow.
48
49 :rtype: list
50 :return: a list of objects
51 """
52 pass
53
54 def _select_ids(self, id_=None, name=None):
55 """
56 Return the id list that corresponds to the given id or name info.
57 """
58 if id_ is None and name is None:
59 self._error('neither id nor name provided', err_type=TypeError)
60 if id_ is not None and name is not None:
61 self._error('both id and name provided', err_type=TypeError)
62 if id_ is None:
63 return [_.id for _ in self.get_previews(name=name)]
64 else:
65 return [id_]
66
67 def _error(self, msg, err_type=RuntimeError):
68 self.log.error(msg)
69 raise err_type(msg)
70
71 def _get_dict(self, meth_name, reply):
72 if reply is None:
73 self._error('%s: no reply' % meth_name)
74 elif isinstance(reply, collections.Mapping):
75 return reply
76 try:
77 return reply[0]
78 except (TypeError, IndexError):
79 self._error('%s: unexpected reply: %r' % (meth_name, reply))
80
81
82 class ObjDatasetContainerClient(ObjClient):
83
84 def _get_container(self, id_, ctype):
85 show_fname = 'show_%s' % ctype.__name__.lower()
86 gi_client = getattr(self.gi, ctype.API_MODULE)
87 show_f = getattr(gi_client, show_fname)
88 res = show_f(id_)
89 cdict = self._get_dict(show_fname, res)
90 cdict['id'] = id_ # overwrite unencoded id
91 c_infos = show_f(id_, contents=True)
92 if not isinstance(c_infos, collections.Sequence):
93 self._error('%s: unexpected reply: %r' % (show_fname, c_infos))
94 c_infos = [ctype.CONTENT_INFO_TYPE(_) for _ in c_infos]
95 return ctype(cdict, content_infos=c_infos, gi=self.obj_gi)
96
97
98 class ObjLibraryClient(ObjDatasetContainerClient):
99 """
100 Interacts with Galaxy libraries.
101 """
102 def __init__(self, obj_gi):
103 super(ObjLibraryClient, self).__init__(obj_gi)
104
105 def create(self, name, description=None, synopsis=None):
106 """
107 Create a data library with the properties defined in the arguments.
108
109 :rtype: :class:`~.wrappers.Library`
110 :return: the library just created
111 """
112 res = self.gi.libraries.create_library(name, description, synopsis)
113 lib_info = self._get_dict('create_library', res)
114 return self.get(lib_info['id'])
115
116 def get(self, id_):
117 """
118 Retrieve the data library corresponding to the given id.
119
120 :rtype: :class:`~.wrappers.Library`
121 :return: the library corresponding to ``id_``
122 """
123 return self._get_container(id_, wrappers.Library)
124
125 def get_previews(self, name=None, deleted=False):
126 dicts = self.gi.libraries.get_libraries(name=name, deleted=deleted)
127 return [wrappers.LibraryPreview(_, gi=self.obj_gi) for _ in dicts]
128
129 def list(self, name=None, deleted=False):
130 """
131 Get libraries owned by the user of this Galaxy instance.
132
133 :type name: str
134 :param name: return only libraries with this name
135 :type deleted: bool
136 :param deleted: if ``True``, return libraries that have been deleted
137
138 :rtype: list of :class:`~.wrappers.Library`
139 """
140 dicts = self.gi.libraries.get_libraries(name=name, deleted=deleted)
141 if not deleted:
142 # return Library objects only for not-deleted libraries since Galaxy
143 # does not filter them out and Galaxy release_14.08 and earlier
144 # crashes when trying to get a deleted library
145 return [self.get(_['id']) for _ in dicts if not _['deleted']]
146 else:
147 return [self.get(_['id']) for _ in dicts]
148
149 def delete(self, id_=None, name=None):
150 """
151 Delete the library with the given id or name.
152
153 Note that the same name can map to multiple libraries.
154
155 .. warning::
156 Deleting a data library is irreversible - all of the data from
157 the library will be permanently deleted.
158 """
159 for id_ in self._select_ids(id_=id_, name=name):
160 res = self.gi.libraries.delete_library(id_)
161 if not isinstance(res, collections.Mapping):
162 self._error('delete_library: unexpected reply: %r' % (res,))
163
164
165 class ObjHistoryClient(ObjDatasetContainerClient):
166 """
167 Interacts with Galaxy histories.
168 """
169
170 def __init__(self, obj_gi):
171 super(ObjHistoryClient, self).__init__(obj_gi)
172
173 def create(self, name=None):
174 """
175 Create a new Galaxy history, optionally setting its name.
176
177 :rtype: :class:`~.wrappers.History`
178 :return: the history just created
179 """
180 res = self.gi.histories.create_history(name=name)
181 hist_info = self._get_dict('create_history', res)
182 return self.get(hist_info['id'])
183
184 def get(self, id_):
185 """
186 Retrieve the history corresponding to the given id.
187
188 :rtype: :class:`~.wrappers.History`
189 :return: the history corresponding to ``id_``
190 """
191 return self._get_container(id_, wrappers.History)
192
193 def get_previews(self, name=None, deleted=False):
194 dicts = self.gi.histories.get_histories(name=name, deleted=deleted)
195 return [wrappers.HistoryPreview(_, gi=self.obj_gi) for _ in dicts]
196
197 def list(self, name=None, deleted=False):
198 """
199 Get histories owned by the user of this Galaxy instance.
200
201 :type name: str
202 :param name: return only histories with this name
203 :type deleted: bool
204 :param deleted: if ``True``, return histories that have been deleted
205
206 :rtype: list of :class:`~.wrappers.History`
207 """
208 dicts = self.gi.histories.get_histories(name=name, deleted=deleted)
209 return [self.get(_['id']) for _ in dicts]
210
211 def delete(self, id_=None, name=None, purge=False):
212 """
213 Delete the history with the given id or name.
214
215 Note that the same name can map to multiple histories.
216
217 :type purge: bool
218 :param purge: if ``True``, also purge (permanently delete) the history
219
220 .. note::
221 For the purge option to work, the Galaxy instance must have the
222 ``allow_user_dataset_purge`` option set to ``True`` in the
223 ``config/galaxy.ini`` configuration file.
224 """
225 for id_ in self._select_ids(id_=id_, name=name):
226 res = self.gi.histories.delete_history(id_, purge=purge)
227 if not isinstance(res, collections.Mapping):
228 self._error('delete_history: unexpected reply: %r' % (res,))
229
230
231 class ObjWorkflowClient(ObjClient):
232 """
233 Interacts with Galaxy workflows.
234 """
235
236 def __init__(self, obj_gi):
237 super(ObjWorkflowClient, self).__init__(obj_gi)
238
239 def import_new(self, src):
240 """
241 Imports a new workflow into Galaxy.
242
243 :type src: dict or str
244 :param src: deserialized (dictionary) or serialized (str) JSON
245 dump of the workflow (this is normally obtained by exporting
246 a workflow from Galaxy).
247
248 :rtype: :class:`~.wrappers.Workflow`
249 :return: the workflow just imported
250 """
251 if isinstance(src, collections.Mapping):
252 wf_dict = src
253 else:
254 try:
255 wf_dict = json.loads(src)
256 except (TypeError, ValueError):
257 self._error('src not supported: %r' % (src,))
258 wf_info = self.gi.workflows.import_workflow_json(wf_dict)
259 return self.get(wf_info['id'])
260
261 def import_shared(self, id_):
262 """
263 Imports a shared workflow to the user's space.
264
265 :type id_: str
266 :param id_: workflow id
267
268 :rtype: :class:`~.wrappers.Workflow`
269 :return: the workflow just imported
270 """
271 wf_info = self.gi.workflows.import_shared_workflow(id_)
272 return self.get(wf_info['id'])
273
274 def get(self, id_):
275 """
276 Retrieve the workflow corresponding to the given id.
277
278 :rtype: :class:`~.wrappers.Workflow`
279 :return: the workflow corresponding to ``id_``
280 """
281 res = self.gi.workflows.show_workflow(id_)
282 wf_dict = self._get_dict('show_workflow', res)
283 return wrappers.Workflow(wf_dict, gi=self.obj_gi)
284
285 # the 'deleted' option is not available for workflows
286 def get_previews(self, name=None, published=False):
287 dicts = self.gi.workflows.get_workflows(name=name, published=published)
288 return [wrappers.WorkflowPreview(_, gi=self.obj_gi) for _ in dicts]
289
290 # the 'deleted' option is not available for workflows
291 def list(self, name=None, published=False):
292 """
293 Get workflows owned by the user of this Galaxy instance.
294
295 :type name: str
296 :param name: return only workflows with this name
297 :type published: bool
298 :param published: if ``True``, return also published workflows
299
300 :rtype: list of :class:`~.wrappers.Workflow`
301 """
302 dicts = self.gi.workflows.get_workflows(name=name, published=published)
303 return [self.get(_['id']) for _ in dicts]
304
305 def delete(self, id_=None, name=None):
306 """
307 Delete the workflow with the given id or name.
308
309 Note that the same name can map to multiple workflows.
310
311 .. warning::
312 Deleting a workflow is irreversible - all of the data from
313 the workflow will be permanently deleted.
314 """
315 for id_ in self._select_ids(id_=id_, name=name):
316 res = self.gi.workflows.delete_workflow(id_)
317 if not isinstance(res, six.string_types):
318 self._error('delete_workflow: unexpected reply: %r' % (res,))
319
320
321 class ObjToolClient(ObjClient):
322 """
323 Interacts with Galaxy tools.
324 """
325 def __init__(self, obj_gi):
326 super(ObjToolClient, self).__init__(obj_gi)
327
328 def get(self, id_, io_details=False, link_details=False):
329 """
330 Retrieve the tool corresponding to the given id.
331
332 :type io_details: bool
333 :param io_details: if True, get also input and output details
334
335 :type link_details: bool
336 :param link_details: if True, get also link details
337
338 :rtype: :class:`~.wrappers.Tool`
339 :return: the tool corresponding to ``id_``
340 """
341 res = self.gi.tools.show_tool(id_, io_details=io_details,
342 link_details=link_details)
343 tool_dict = self._get_dict('show_tool', res)
344 return wrappers.Tool(tool_dict, gi=self.obj_gi)
345
346 def get_previews(self, name=None, trackster=None):
347 """
348 Get the list of tools installed on the Galaxy instance.
349
350 :type name: str
351 :param name: return only tools with this name
352
353 :type trackster: bool
354 :param trackster: if True, only tools that are compatible with
355 Trackster are returned
356
357 :rtype: list of :class:`~.wrappers.Tool`
358 """
359 dicts = self.gi.tools.get_tools(name=name, trackster=trackster)
360 return [wrappers.Tool(_, gi=self.obj_gi) for _ in dicts]
361
362 # the 'deleted' option is not available for tools
363 def list(self, name=None, trackster=None):
364 """
365 Get the list of tools installed on the Galaxy instance.
366
367 :type name: str
368 :param name: return only tools with this name
369
370 :type trackster: bool
371 :param trackster: if True, only tools that are compatible with
372 Trackster are returned
373
374 :rtype: list of :class:`~.wrappers.Tool`
375 """
376 # dicts = self.gi.tools.get_tools(name=name, trackster=trackster)
377 # return [self.get(_['id']) for _ in dicts]
378 # As of 2015/04/15, GET /api/tools returns also data manager tools for
379 # non-admin users, see
380 # https://trello.com/c/jyl0cvFP/2633-api-tool-list-filtering-doesn-t-filter-data-managers-for-non-admins
381 # Trying to get() a data manager tool would then return a 404 Not Found
382 # error.
383 # Moreover, the dicts returned by gi.tools.get_tools() are richer than
384 # those returned by get(), so make this an alias for get_previews().
385 return self.get_previews(name, trackster)
386
387
388 class ObjJobClient(ObjClient):
389 """
390 Interacts with Galaxy jobs.
391 """
392 def __init__(self, obj_gi):
393 super(ObjJobClient, self).__init__(obj_gi)
394
395 def get(self, id_, full_details=False):
396 """
397 Retrieve the job corresponding to the given id.
398
399 :type full_details: bool
400 :param full_details: if ``True``, return the complete list of details
401 for the given job.
402
403 :rtype: :class:`~.wrappers.Job`
404 :return: the job corresponding to ``id_``
405 """
406 res = self.gi.jobs.show_job(id_, full_details)
407 job_dict = self._get_dict('job_tool', res)
408 return wrappers.Job(job_dict, gi=self.obj_gi)
409
410 def get_previews(self):
411 dicts = self.gi.jobs.get_jobs()
412 return [wrappers.JobPreview(_, gi=self.obj_gi) for _ in dicts]
413
414 def list(self):
415 """
416 Get the list of jobs of the current user.
417
418 :rtype: list of :class:`~.wrappers.Job`
419 """
420 dicts = self.gi.jobs.get_jobs()
421 return [self.get(_['id']) for _ in dicts]