1
+ import xmlrpc .client
2
+ import traceback
3
+ import util
4
+
5
+ BOA_PROXY = "http://boa.cs.iastate.edu/boa/?q=boa/api"
6
+
7
+ class NotLoggedInException (Exception ):
8
+ pass
9
+
10
+ class BoaException (Exception ):
11
+ pass
12
+
13
+ class BoaClient (object ):
14
+ """ A client class for accessing boa's api
15
+
16
+ Attributes:
17
+ server (xmlrpc.client.ServerProxy):
18
+ trans (xmlrpc.client.Transport)
19
+ """
20
+
21
+ def __init__ (self ):
22
+ """Create a new Boa API client, using the standard domain/path."""
23
+ self .trans = util .CookiesTransport ()
24
+ self .__logged_in = False
25
+ self .server = xmlrpc .client .ServerProxy (BOA_PROXY , transport = self .trans )
26
+
27
+ def login (self , username , password ):
28
+ """log into the boa framework using the remote api
29
+
30
+ Args:
31
+ username (str): username for boa account
32
+ password (str): password for boa account
33
+ """
34
+ try :
35
+ self .__logged_in = True
36
+ response = self .server .user .login (username , password )
37
+ self .trans .add_csrf (response ["token" ])
38
+ return response
39
+ except xmlrpc .client .Fault as e :
40
+ raise BoaException (e ).with_traceback (e .__traceback__ )
41
+
42
+ def close (self ):
43
+ """Log out of the boa framework using the remote api
44
+
45
+ Raises:
46
+ BoaException: if theres an issue reading from the server
47
+ """
48
+ self .ensure_logged_in ()
49
+ try :
50
+ self .server .user .logout ()
51
+ self .__logged_in = False
52
+ except xmlrpc .client .Fault as e :
53
+ raise BoaException (e ).with_traceback (e .__traceback__ )
54
+
55
+ def ensure_logged_in (self ):
56
+ """Checks if a user is currently logged in through the remote api
57
+
58
+ Returns:
59
+ bool: True if user is logged in, false if otherwise
60
+
61
+ Raises:
62
+ NotLoggedInException: if user is not currently logged in
63
+ """
64
+ if not self .__logged_in :
65
+ raise NotLoggedInException ("User not currently logged in" )
66
+
67
+ def datasets (self ):
68
+ """ Retrieves datasetsets currently provided by boa
69
+
70
+ Returns:
71
+ list: a list of boa datasets
72
+
73
+ Raises:
74
+ BoaException: if theres an issue reading from the server
75
+ """
76
+ self .ensure_logged_in ()
77
+ try :
78
+ return self .server .boa .datasets ()
79
+ except xmlrpc .client .Fault as e :
80
+ raise BoaException (e ).with_traceback (e .__traceback__ )
81
+
82
+ def dataset_names (self ):
83
+ """Retrieves a list of names of all datasets provided by boa
84
+
85
+ Returns:
86
+ list: the dataset names
87
+
88
+ Raises:
89
+ BoaException: if theres an issue reading from the server
90
+ """
91
+ self .ensure_logged_in ()
92
+ try :
93
+ dataset_names = []
94
+ datasets = self .datasets ()
95
+ for x in datasets :
96
+ dataset_names .append (x ['name' ])
97
+ return dataset_names
98
+ except xmlrpc .client .Fault as e :
99
+ raise BoaException (e ).with_traceback (e .__traceback__ )
100
+
101
+ def get_dataset (self , name ):
102
+ """Retrieves a dataset given a name.
103
+
104
+ Args:
105
+ name (str): The name of the input dataset to return.
106
+
107
+ Returns:
108
+ dict: a dictionary with the keys id and name
109
+
110
+ Raises:
111
+ BoaException: if theres an issue reading from the server
112
+ """
113
+ self .ensure_logged_in ()
114
+ try :
115
+ for x in self .datasets ():
116
+ if x ['name' ] == name :
117
+ return x
118
+ return None
119
+ except xmlrpc .client .Fault as e :
120
+ raise BoaException (e ).with_traceback (e .__traceback__ )
121
+
122
+ def last_job (self ):
123
+ """Retrieves the most recently submitted job
124
+
125
+ Returns:
126
+ JobHandle: the last submitted job
127
+
128
+ Raises:
129
+ BoaException: if theres an issue reading from the server
130
+ """
131
+ self .ensure_logged_in ()
132
+ try :
133
+ jobs = self .job_list (False , 0 , 1 )
134
+ return jobs [0 ]
135
+ except xmlrpc .client .Fault as e :
136
+ raise BoaException (e ).with_traceback (e .__traceback__ )
137
+
138
+ def job_count (self , pub_only = False ):
139
+ """Retrieves the number of jobs submitted by a user
140
+
141
+ Args:
142
+ pub_only (bool, optional): if true, return only public jobs
143
+ otherwise return all jobs
144
+
145
+ Returns:
146
+ int: the number of jobs submitted by a user
147
+
148
+ Raises:
149
+ BoaException: if theres an issue reading from the server
150
+ """
151
+ self .ensure_logged_in ()
152
+ try :
153
+ return self .server .boa .count (pub_only )
154
+ except xmlrpc .client .Fault as e :
155
+ raise BoaException (e ).with_traceback (e .__traceback__ )
156
+
157
+ def query (self , query , dataset = None ):
158
+ """Submits a new query to Boa to query the specified and returns a handle to the new job.
159
+
160
+ Args:
161
+ query (str): a boa query represented as a string.
162
+ dataset (str, optional): the name of the input dataset.
163
+
164
+ Returns:
165
+ (JobHandle) a job
166
+
167
+ Raises:
168
+ BoaException: if theres an issue reading from the server
169
+ """
170
+ self .ensure_logged_in ()
171
+ try :
172
+ id = 0 if dataset is None else dataset .get_id ()
173
+ job = self .server .boa .submit (query , self .datasets ()[id ]['id' ])
174
+ return util .parse_job (self , job )
175
+ except xmlrpc .client .Fault as e :
176
+ raise BoaException (e ).with_traceback (e .__traceback__ )
177
+
178
+ def get_job (self , id ):
179
+ """Retrieves a job given an id.
180
+
181
+ Args:
182
+ id (int): the id of the job you want to retrieve
183
+
184
+ Returns:
185
+ JobHandle: the desired job.
186
+
187
+ Raises:
188
+ BoaException: if theres an issue reading from the server
189
+ """
190
+ self .ensure_logged_in ()
191
+ try :
192
+ return util .parse_job (self , self .server .boa .job (id ))
193
+ except xmlrpc .client .Fault as e :
194
+ raise BoaException (e ).with_traceback (e .__traceback__ )
195
+
196
+ def job_list (self , pub_only = False , offset = 0 , length = 1000 ):
197
+ """Returns a list of the most recent jobs, based on an offset and length.
198
+
199
+ This includes public and private jobs. Returned jobs are ordered from newest to oldest
200
+
201
+ Args:
202
+ pub_only (bool, optional): if true, only return public jobs otherwise return all jobs
203
+ offset (int, optional): the starting offset
204
+ length (int, optional): the number of jobs (at most) to return
205
+
206
+ Returns:
207
+ list: a list of jobs where each element is a jobHandle
208
+
209
+ Raises:
210
+ BoaException: if theres an issue reading from the server
211
+ """
212
+ self .ensure_logged_in ()
213
+ try :
214
+ list = self .server .boa .jobs (pub_only , offset , length )
215
+ newDict = []
216
+ if (len (list ) > 0 ):
217
+ for i in list :
218
+ newDict .append (util .parse_job (self , i ))
219
+ return newDict
220
+ except xmlrpc .client .Fault as e :
221
+ raise BoaException (e ).with_traceback (e .__traceback__ )
222
+
223
+ def stop (self , job ):
224
+ """Stops the execution of a job
225
+
226
+ Args:
227
+ job (JobHandle): the job whose execution you want to stop
228
+
229
+ Raises:
230
+ BoaException: if theres an issue reading from the server
231
+ """
232
+ self .ensure_logged_in ()
233
+ try :
234
+ self .server .job .stop (job .id )
235
+ except xmlrpc .client .Fault as e :
236
+ raise BoaException (e ).with_traceback (e .__traceback__ )
237
+
238
+ def resubmit (self , job ):
239
+ """Resubmits a job to the framework
240
+
241
+ Args:
242
+ job (JobHandle): The job you want to resubmit
243
+
244
+ Raises:
245
+ BoaException: if theres an issue reading from the server
246
+ """
247
+ self .ensure_logged_in ()
248
+ try :
249
+ self .server .job .resubmit (job .id )
250
+ except xmlrpc .client .Fault as e :
251
+ raise BoaException (e ).with_traceback (e .__traceback__ )
252
+
253
+ def delete (self , job ):
254
+ """Deletes this job from the framework.
255
+
256
+ Args:
257
+ job (JobHandle): the job you want to delete
258
+
259
+ Raises:
260
+ BoaException: if theres an issue reading from the server
261
+ """
262
+ self .ensure_logged_in ()
263
+ try :
264
+ self .server .job .delete (job .id )
265
+ except xmlrpc .client .Fault as e :
266
+ raise BoaException (e ).with_traceback (e .__traceback__ )
267
+
268
+ def set_public (self , job , is_public ):
269
+ """Modifies the public/private status of this job.
270
+
271
+ Args:
272
+ is_public (bool): 'True' to make it public, False to make it private
273
+ job (JobHandle)
274
+
275
+ Raises:
276
+ BoaException: if theres an issue reading from the server
277
+ """
278
+ self .ensure_logged_in ()
279
+ try :
280
+ if is_public is True :
281
+ self .server .job .setpublic (job .id , 1 )
282
+ else :
283
+ self .server .job .setpublic (job .id , 0 )
284
+ except xmlrpc .client .Fault as e :
285
+ raise BoaException (e ).with_traceback (e .__traceback__ )
286
+
287
+ def public_status (self , job ):
288
+ """Get the jobs public/private status.
289
+
290
+ Args:
291
+ job (JobHandle)
292
+
293
+ Raises:
294
+ BoaException: if theres an issue reading from the server
295
+ """
296
+ self .ensure_logged_in ()
297
+ try :
298
+ result = self .server .job .public (job .id )
299
+ if result is 1 :
300
+ return True
301
+ else :
302
+ return False
303
+ except xmlrpc .client .Fault as e :
304
+ raise BoaException (e ).with_traceback (e .__traceback__ )
305
+
306
+ def get_url (self , job ):
307
+ """Retrieves the jobs URL.
308
+
309
+ Args:
310
+ job (JobHandle)
311
+
312
+ Raises:
313
+ BoaException: if theres an issue reading from the server
314
+ """
315
+ self .ensure_logged_in ()
316
+ try :
317
+ return self .server .job .url (job .id )
318
+ except xmlrpc .client .Fault as e :
319
+ raise BoaException (e ).with_traceback (e .__traceback__ )
320
+
321
+ def public_url (self , job ):
322
+ """Get the jobs public page URL.
323
+
324
+ Args:
325
+ job (JobHandle)
326
+
327
+ Raises:
328
+ BoaException: if theres an issue reading from the server
329
+ """
330
+ self .ensure_logged_in ()
331
+ try :
332
+ return self .server .job .publicurl (job .id )
333
+ except xmlrpc .client .Fault as e :
334
+ raise BoaException (e ).with_traceback (e .__traceback__ )
335
+
336
+ def get_compiler_errors (self , job ):
337
+ """Return any errors from trying to compile the job.
338
+
339
+ Args:
340
+ job (JobHandle)
341
+
342
+ Raises:
343
+ BoaException: if theres an issue reading from the server
344
+ """
345
+ self .ensure_logged_in ()
346
+ try :
347
+ return self .server .job .compilerErrors (job .id )
348
+ except xmlrpc .client .Fault as e :
349
+ raise BoaException (e ).with_traceback (e .__traceback__ )
350
+
351
+ def source (self , job ):
352
+ """Return the source query for this job.
353
+
354
+ Args:
355
+ job (JobHandle)
356
+
357
+ Raises:
358
+ BoaException: if theres an issue reading from the server
359
+ """
360
+ self .ensure_logged_in ()
361
+ try :
362
+ return self .server .job .source (job .id )
363
+ except xmlrpc .client .Fault as e :
364
+ raise BoaException (e ).with_traceback (e .__traceback__ )
365
+
366
+ def output (self , job ):
367
+ """Return the output for this job, if it finished successfully and has an output.
368
+
369
+ Raises:
370
+ BoaException: if theres an issue reading from the server
371
+ """
372
+ self .ensure_logged_in ()
373
+ try :
374
+ if job .exec_status != "Finished" :
375
+ return "Job is currently running"
376
+ return self .server .job .output (job .id )
377
+ except xmlrpc .client .Fault as e :
378
+ raise BoaException (e ).with_traceback (e .__traceback__ )
0 commit comments