1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
|
"""
The VAO Package and Tasking Interfaces.
The tasking interface defines the python-side classes needed to manage and
execute host processes that implement the "VAO Package" binary interface.
These classes load the package (i.e. execute the binary as a connected
processes and interogate it for a list of available tasks). The VOTask
interface is used to set the input parameters, execute the task and process
the result parameter set (PSet).
The VOPSet interface manages a collection of VOParam parameter objects:
input parameters will typically define options for the host task (e.g.
input file, processing options, etc), while output parameters may contain
arbitrary objects returned by the task (e.g. a FITS file or VOTable) or
strings which make up the stdout/stderr streams of the task. A VOParam has
attributes needed to describe the type of parameter, by selecting
parameters of the same name from a PSet (e.g. 'msgs') an application can
process multiple output objects as needed.
A 'task' is a computational component which can be executed as a process by
the host operating system (or a related environment such as a cluster).
Tasks may be written in any language so long as the defined tasking
interface is observed. The 'package' refered to here should not be
confused with a Python package. A Python package is an element of Python,
a 'package' as referred to here is a collection of tasks and their
associated metadata.
"""
import sys
import os
import re
import glob
# Module Globals and Functions
""" The Package search path.
"""
vopkg_path = ['.'] # always include the cwd
vopkg_extn = ".vop"
pkg_list = [] # scan package dirs to get list of packages
pkg_struct = None # dictionary of package data in the form
# key = pkgname
# value = tuple(<path>, [<tasklist>])
def setPkgDirs (dirs):
''' Set the VO package search path as an absolute list of directories.
@param dirs list of directory to use as search path
Returns: Nothing
'''
vopkg_path = [.] + dirs
def addPkgDir (dir):
''' Append the given directory to the package search path.
@param dir the directory to add to the search path
Returns: Nothing
'''
vopkg_path.append(dir)
def getPkgDirs ():
''' Get the VO package search path as a list of directories.
Returns: Nothing
'''
return (vopkg_path)
def pkgList (pattern=None):
''' Get the list of available packages.
@param pattern the package name pattern to match
Returns: A list available package names.
'''
pat = pattern # construct the pattern string
if (pattern == None):
pat = "*"
pkg_list = [] # scan package dirs to get list of packages
for dir in vopkg_path:
if os.path.isdir(dir):
pfiles = glob.glob(dir + "/" + pat + vopkg_extn)
for f in pfiles:
root,ext = os.path.splitext(os.path.basename(f))
pkg_list.append(root)
pkg_struct[root] = [ f ]
else:
root,ext = os.path.splitext(os.path.basename(dir))
if (re.search(pattern,root)):
pkg_list.append(root)
pkg_struct[root] = [ dir ]
# Save just the package names as a valid list.
pkg_list = pkg_struct.keys()
# Scan the package list, to get a list of tasks in each package.
for pkg in pkg_list:
tlist = vop_taskList (pkg_struct[pkg][0]) # get task list
pkg_struct[pkg].append(tlist) # save in struct
def scan ():
''' Force a re-scan of the package search path for available package
files. Each directory in the path is searched for a ".vop" file
indicating a VO package executable, this file is then interrogated
for a list of tasks. This allows new package files to be installed
(or removed) as the module is running.
Returns: Nothing
'''
lst = pkgList ("*") # scan all packages
def loadPackage (name, file=None):
''' Load the package. Effectively all this does is create a VOPackage
object from the metadata for the named package, this requires
that we start the package binary to get the metadata information.
If a 'file' parameter is specified we open that file regardless of
the name, allowing any VOPackage file to be used dynamically.
When a package is loaded, bindings for each of the tasks are generated
automatically in order to allow direct access to the task. As an
example:
>>> vop = loadPackage ("vo-cli") # from search path
>>> results = vop.voregistry (searchTerm="quasar")
>>> printResultPset (results) # user-defined function
When developing a package or when an app needs to explicitly include
a new package, it may be accessed directly as:
>>> vop = loadPackage ("vo-cli",file="/path/devpkg.e")
@param name the package name
@param file the package binary file to execute
Returns: The loaded VOPackage object
'''
pass
def taskList (pkg, pattern=None):
''' List the tasks available in a package.
@param pkg the package name
@param pattern the task pattern name to match
Returns: A list of tasks available in the package who's name
matches the 'pattern' string.
'''
pass
def pkgAttrs (pkg):
''' Get the attributes for the named package, i.e. create a dictionary
of package metadata.
@param pkg the package name
Returns: A dictionary of the package attributes.
'''
pass
def taskAttrs (pkg, task):
''' Get the attributes for the named task in the package, i.e. create
a dictionary of task metadata.
@param pkg the package name
@param task the task name
Returns: A dictionary of the task attributes.
'''
pass
class VOPackageError (Exception):
''' A base class for VO Package errors. Use of this exception is TBD.
'''
pass
class VOPackage:
''' A class defining a VOPackage object. A VOPackage is a collection
of tasks as well as metadata about the package itself. The
functional part of the package is implemented in a binary file
executing as a connected process, task discovery and execution are
implemented as commands sent to the package binary, results are
returned over the IPC channel as a stream of parameter objects.
'''
# Class attributes
name = None # package name
descr = None # description string
author = None # package author
contact = None # contact email address
iconUrl = None # URL to package icon
version = None # package version string
dir = None # the directory containing the package
binfile = None # the name of the package binary
def __init__ (self, dirs):
pass
def __iter__ (self, dirs): # get next task in the package
pass
def taskList (self, pattern=None):
''' Get the list of tasks in the package which match a pattern string.
If no pattern is specified, all tasks are returned.
@param pattern the parameter name to match
Returns: A list of available tasks who's name matches
the pattern string.
'''
pass
def pkgAttrs (self):
''' Get the attributes for the VO Package as a dictionary string.
Returns: A dictionary of the package attributes
'''
pass
class VOTaskError (Exception):
''' A base class for Task execution errors.
'''
pass
class VOTaskParameterError (VOTaskError):
''' an exception indicating an error in the task calling parameters
'''
pass
class VOTaskExecutionError (VOTaskError):
''' an exception indicating an error when executing the task
'''
pass
class VOTask:
''' A class defining a VO Task object.
'''
name = None # task name
pkg = None # parent package name
descr = None # task description string
params = None # task input parameter set
status = None # task execution return status (OK or ERROR)
msg = None # task execution return error message
def __init__ (self, name, pkg, descr, params):
''' create the VOTask instance
'''
pass
def taskAttrs (self):
''' Get the attributes of the task as a dictionary.
Returns: A dictionary of the task attributes
'''
pass
def setParams (pset):
''' Set the task parameter pset. Parameters in the pset argument
will be used set the values for the task parameter pset, i.e.
the argument pset can be just a subset of the task parameters,
we'll match the names and set the values for only those params.
If the argument pset contains a parameter not already in the
task input pset, it will be added as a new parameter.
@param pset parameter set to load
Returns: A dictionary of the task attributes
'''
pass
def getParams ():
''' Set the task parameter pset.
Returns: The task parameter pset.
'''
pass
def setCallback (pattern, func):
''' Set a callback function to be run whenever a parameter name
that matches the pattern is encountered. Pattern applies only
to the output parameter set.
@param pattern the parameter name to match
@param func the function to be called when parameter encountered
Returns: nothing
'''
pass
def executeSync (self):
''' Execute the task as a synchronous process.
@throws VOTaskParameterError thrown when parameters are invalid
@throws VOTaskExecutionError thrown when there is an error is
executing a task, e.g. a segfault.
Returns: The result pset.
'''
pass
def executeASync (self):
''' Execute the task as a asynchronous process.
Returns: Nothing
'''
pass
def wait (self):
''' Wait for the exit of an asynchronous execution
@throws VOTaskParameterError thrown when parameters are invalid
@throws VOTaskExecutionError thrown when there is an error is
executing a task, e.g. a segfault.
Returns: The result pset.
'''
pass
def status (self):
''' Get the status of an executing asynchronous task.
Returns: Task exec status ('Pending','Running','Done','Error')
'''
pass
class VOPset:
''' A class defining a PSet object.
'''
name = None # pset name
pkg = None # package name
task = None # task name associated with pset
description = None # pset description name
def __init__ (self, name, type, descr, encoding):
''' create the VOPset instance
'''
pass
def loadPset (pkg=None, task=None, saveFile=None):
''' Load the pset from the named task in the package. If 'saveFile'
is specified the pset is restored from that file.
@param pkg package name
@param task task name
@param saveFile name of the saved parameter file to load
Returns: The loaded PSet
'''
pass
def savePset (saveFile):
''' Save the PSet to the named file. Serialization of the PSet is
TBD, probably some sort of simple XML schema.
@param saveFile name of the saved parameter file
Returns: Nothing
'''
pass
def paramSet (pattern=None):
''' Create pset from params who's name matches the 'pattern' string.
If no pattern is specified, all parameters are returned.
@param pattern parameter pattern name to match
Returns: The constructed PSet
'''
pass
def paramList (pattern=None):
''' Get list of params who's name matches the 'pattern' string. If
no pattern is specified, all parameters are returned.
@param pattern parameter pattern name to match
Returns: Nothing
'''
pass
def addParam (name, type, description, encoding=None):
''' Add a new parameter with the specified attributes to the pset.
@param name name of the parameter to add
@param type parameter type value
@param descr parameter description string
@param encoding parameter encoding
Returns: The created parameter
'''
pass
def delParam (name):
''' Delete the named parameter from the pset.
@param name name of the parameter to delete
Returns: Nothing
'''
pass
def getParam (name):
''' Get the parameter with the given name.
@param name name of the parameter to retrieve
Returns: Requested parameter
'''
pass
class VOParam:
''' A class defining a Parameter object.
'''
name = None # parameter name
type = None # parameter type (string/int/real/bool/blob)
desc = None # parameter description string
encoding = None # encoding of param (i.e. mime type)
def __init__ (self, name, type, descr, encoding):
''' create the VOParam instance
'''
pass
def paramAttrs ():
''' Get the parameter attributes.
Returns: A dictionary of parameter attrbutes
'''
pass
def getValue ():
''' Get the value of the parameter (may be a list)
Returns: The parameter's value
'''
pass
def setValue (val):
''' Set the value of a parameter.
@param val the value of the paramter (arbitrary type)
Returns: Nothing
'''
pass
|