t2-server 0.2.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +11 -6
- data/bin/{delete_all_runs → t2-delete-runs} +51 -9
- data/bin/{run_workflow → t2-run-workflow} +35 -28
- data/bin/{server_info → t2-server-info} +3 -2
- data/lib/t2-server.rb +71 -0
- data/lib/{t2server → t2-server}/exceptions.rb +3 -1
- data/lib/{t2server → t2-server}/run.rb +87 -31
- data/lib/{t2server → t2-server}/server.rb +89 -47
- data/lib/{t2server → t2-server}/xml.rb +36 -1
- data/lib/t2server.rb +3 -39
- data/test/tc_paths.rb +1 -1
- data/test/tc_run.rb +2 -5
- data/test/tc_server.rb +1 -1
- data/test/ts_t2server.rb +5 -2
- metadata +37 -16
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Taverna[http://www.taverna.org.uk/] 2 Server Interaction Gem
|
2
2
|
|
3
3
|
Authors:: Robert Haines
|
4
|
-
Gem Version:: 0.
|
4
|
+
Gem Version:: 0.5.0
|
5
5
|
API Version:: 2.2a1
|
6
6
|
Contact:: mailto:rhaines@manchester.ac.uk
|
7
7
|
URL:: http://taverna.sourceforge.net/
|
@@ -34,17 +34,22 @@ There are two entry points for the T2Server API:
|
|
34
34
|
* T2Server::Server - Use this if you are providing a web interface to one or
|
35
35
|
more Taverna 2 Server instances.
|
36
36
|
|
37
|
+
In both cases the gem should be initialized by requiring the top level ruby
|
38
|
+
file:
|
39
|
+
require 't2-server.rb'
|
40
|
+
|
37
41
|
See the rdoc for more information.
|
38
42
|
|
39
43
|
As well as rdoc there are also a couple of example scripts which
|
40
44
|
demonstrate good use of the T2Server API. These are available in the
|
41
|
-
<tt>bin</tt> directory
|
42
|
-
|
43
|
-
*
|
44
|
-
*
|
45
|
+
<tt>bin</tt> directory but are also installed with the library code when the
|
46
|
+
gem is installed:
|
47
|
+
* t2-run-workflow
|
48
|
+
* t2-server-info
|
49
|
+
* t2-delete-runs
|
45
50
|
Running any of these scripts with a <tt>-h</tt> or <tt>--help</tt>
|
46
51
|
switch will show how to use them, e.g.:
|
47
|
-
|
52
|
+
t2-run-workflow --help
|
48
53
|
|
49
54
|
== Support
|
50
55
|
|
@@ -31,16 +31,21 @@
|
|
31
31
|
#
|
32
32
|
# Author: Robert Haines
|
33
33
|
|
34
|
-
require '
|
34
|
+
require 'rubygems'
|
35
|
+
require 't2-server'
|
35
36
|
require 'optparse'
|
36
37
|
|
37
38
|
# set up options
|
39
|
+
delete_all = false
|
38
40
|
opts = OptionParser.new do |opt|
|
39
|
-
opt.banner = "Usage:
|
41
|
+
opt.banner = "Usage: t2-delete-runs [options] server-address [run-ids...]"
|
40
42
|
opt.separator ""
|
41
|
-
opt.separator " Where server-address is the full URI of the server to"
|
42
|
-
opt.separator "
|
43
|
-
opt.separator " and [options] can be:"
|
43
|
+
opt.separator " Where server-address is the full URI of the server to connect to,"
|
44
|
+
opt.separator " e.g.: http://example.com:8080/taverna, run-ids are the id numbers"
|
45
|
+
opt.separator " of the runs you want to delete and [options] can be:"
|
46
|
+
opt.on("--all", "Delete all runs on the server") do
|
47
|
+
delete_all = true
|
48
|
+
end
|
44
49
|
opt.on_tail("-h", "-?", "--help", "Show this message") do
|
45
50
|
puts opt
|
46
51
|
exit
|
@@ -55,16 +60,53 @@ end
|
|
55
60
|
# parse options
|
56
61
|
opts.parse!
|
57
62
|
|
58
|
-
#
|
59
|
-
|
63
|
+
# get runs and server address from the arguments
|
64
|
+
runs = []
|
65
|
+
address = ""
|
66
|
+
for arg in ARGV
|
67
|
+
if arg.match(/https?:\/\//) == nil
|
68
|
+
runs << arg
|
69
|
+
else
|
70
|
+
address = arg
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# can't do anything without a server address
|
75
|
+
if address == ""
|
60
76
|
puts opts
|
61
77
|
exit 1
|
62
78
|
end
|
63
79
|
|
64
|
-
# connect
|
80
|
+
# connect...
|
65
81
|
begin
|
66
|
-
T2Server::Server.connect(ARGV[0])
|
82
|
+
server = T2Server::Server.connect(ARGV[0])
|
67
83
|
rescue T2Server::T2ServerError => e
|
68
84
|
puts e
|
69
85
|
exit 1
|
70
86
|
end
|
87
|
+
|
88
|
+
# ...and delete them!
|
89
|
+
if delete_all
|
90
|
+
begin
|
91
|
+
server.delete_all_runs
|
92
|
+
rescue T2Server::AuthorizationError => ae
|
93
|
+
puts "You are not authorized to delete runs on this server."
|
94
|
+
rescue T2Server::T2ServerError => e
|
95
|
+
puts "There was a problem while deleting runs. Some may remain on the server."
|
96
|
+
end
|
97
|
+
else
|
98
|
+
for run in runs
|
99
|
+
begin
|
100
|
+
server.delete_run(run)
|
101
|
+
rescue T2Server::RunNotFoundError => rnf
|
102
|
+
puts "Run '#{run}' not found - skipping."
|
103
|
+
next
|
104
|
+
rescue T2Server::AuthorizationError => ae
|
105
|
+
puts "You are not authorized to delete run '#{run}' - skipping."
|
106
|
+
next
|
107
|
+
rescue T2Server::T2ServerError => e
|
108
|
+
puts "There was a problem while deleting run '#{run}' - skipping."
|
109
|
+
next
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -31,39 +31,39 @@
|
|
31
31
|
#
|
32
32
|
# Author: Robert Haines
|
33
33
|
|
34
|
-
require '
|
34
|
+
require 'rubygems'
|
35
|
+
require 't2-server'
|
35
36
|
require 'optparse'
|
36
37
|
|
37
38
|
# go through the outputs and either print the contents
|
38
39
|
# out or save them to a file.
|
39
40
|
# if the output is a list, it appears as a directory so
|
40
41
|
# all the individual entries must be grabbed from there.
|
41
|
-
def get_outputs(run,
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
puts "written to file: #{filename}"
|
56
|
-
end
|
42
|
+
def get_outputs(run, refs)
|
43
|
+
# get a list of the outputs
|
44
|
+
lists, items = run.ls("out")
|
45
|
+
|
46
|
+
# go through the lists
|
47
|
+
lists.each do |l|
|
48
|
+
print " #{l} -> "
|
49
|
+
p run.get_output("#{l}", refs)
|
50
|
+
end
|
51
|
+
|
52
|
+
# go through the singletons
|
53
|
+
items.each do |i|
|
54
|
+
print " #{i} -> "
|
55
|
+
p run.get_output("#{i}", refs)
|
57
56
|
end
|
58
|
-
end
|
57
|
+
end
|
59
58
|
|
60
59
|
# set up options
|
61
60
|
inputs = {}
|
62
61
|
wkf_file = ""
|
63
|
-
|
62
|
+
output_refs = false
|
64
63
|
baclava_out = ""
|
64
|
+
delete_run = false
|
65
65
|
opts = OptionParser.new do |opt|
|
66
|
-
opt.banner = "Usage:
|
66
|
+
opt.banner = "Usage: t2-run-workflow [options] server-address"
|
67
67
|
opt.separator ""
|
68
68
|
opt.separator " Where server-address is the full URI of the server to"
|
69
69
|
opt.separator " connect to, e.g.: http://example.com:8080/taverna"
|
@@ -73,7 +73,7 @@ opts = OptionParser.new do |opt|
|
|
73
73
|
wkf_file = val
|
74
74
|
end
|
75
75
|
opt.on("-i INPUT:VALUE", "--input=INPUT:VALUE", "Set input port INPUT to VALUE") do |val|
|
76
|
-
input, value = val.chomp.split(':')
|
76
|
+
input, value = val.chomp.split(':', 2)
|
77
77
|
inputs[input] = value
|
78
78
|
end
|
79
79
|
opt.on("-b BACLAVA", "--baclava-in=BACLAVA", "Set baclava file for input port values") do |val|
|
@@ -87,9 +87,14 @@ opts = OptionParser.new do |opt|
|
|
87
87
|
baclava_out = "out.xml"
|
88
88
|
end
|
89
89
|
end
|
90
|
-
opt.on("-
|
91
|
-
"
|
92
|
-
|
90
|
+
opt.on("-r", "--output-refs", "Return URIs that point to the data items " +
|
91
|
+
"of the output rather than the data items themselves.") do |val|
|
92
|
+
output_refs = val
|
93
|
+
end
|
94
|
+
opt.on("-D", "--delete", "Delete the run from the server when it is " +
|
95
|
+
"complete. By default the run and its results are preserved. Note that " +
|
96
|
+
"the run will still be deleted when its expiry time is reached") do |val|
|
97
|
+
delete_run = val
|
93
98
|
end
|
94
99
|
opt.on_tail("-h", "-?", "--help", "Show this message") do
|
95
100
|
puts opt
|
@@ -166,10 +171,12 @@ if exitcd == 0
|
|
166
171
|
puts "Baclava file written to '#{baclava_out}'"
|
167
172
|
else
|
168
173
|
puts "Outputs:"
|
169
|
-
get_outputs(run,
|
174
|
+
get_outputs(run, output_refs)
|
170
175
|
end
|
171
176
|
end
|
172
177
|
|
173
|
-
# delete run
|
174
|
-
|
175
|
-
|
178
|
+
# delete run?
|
179
|
+
if delete_run
|
180
|
+
run.delete
|
181
|
+
puts "Run deleted"
|
182
|
+
end
|
@@ -31,11 +31,12 @@
|
|
31
31
|
#
|
32
32
|
# Author: Robert Haines
|
33
33
|
|
34
|
-
require '
|
34
|
+
require 'rubygems'
|
35
|
+
require 't2-server'
|
35
36
|
require 'optparse'
|
36
37
|
|
37
38
|
opts = OptionParser.new do |opt|
|
38
|
-
opt.banner = "Usage:
|
39
|
+
opt.banner = "Usage: t2-server-info [options] server-address"
|
39
40
|
opt.separator ""
|
40
41
|
opt.separator " Where server-address is the full URI of the server to"
|
41
42
|
opt.separator " connect to, e.g.: http://example.com:8080/taverna"
|
data/lib/t2-server.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright (c) 2010, The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 't2-server/xml'
|
34
|
+
require 't2-server/exceptions'
|
35
|
+
require 't2-server/server'
|
36
|
+
require 't2-server/run'
|
37
|
+
|
38
|
+
# This is a Ruby library to interface with the Taverna 2 Server REST API.
|
39
|
+
#
|
40
|
+
# There are two API entry points:
|
41
|
+
# * T2Server::Run - Use this for running single jobs on a server.
|
42
|
+
# * T2Server::Server - Use this if you are providing a web interface to a
|
43
|
+
# Taverna 2 Server instance.
|
44
|
+
module T2Server
|
45
|
+
# The version of this library
|
46
|
+
GEM_VERSION = "0.5.0"
|
47
|
+
# The version of the Taverna 2 Server API that this library can interface with
|
48
|
+
API_VERSION = "2.2a1"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Add methods to the String class to operate on file paths.
|
52
|
+
class String
|
53
|
+
# :call-seq:
|
54
|
+
# str.strip_path -> string
|
55
|
+
#
|
56
|
+
# Returns a new String with one leading and one trailing slash
|
57
|
+
# removed from the ends of _str_ (if present).
|
58
|
+
def strip_path
|
59
|
+
self.gsub(/^\//, "").chomp("/")
|
60
|
+
end
|
61
|
+
|
62
|
+
# :call-seq:
|
63
|
+
# str.strip_path! -> str or nil
|
64
|
+
#
|
65
|
+
# Modifies _str_ in place as described for String#strip_path,
|
66
|
+
# returning _str_, or returning +nil+ if no modifications were made.
|
67
|
+
def strip_path!
|
68
|
+
g = self.gsub!(/^\//, "")
|
69
|
+
self.chomp!("/") || g
|
70
|
+
end
|
71
|
+
end
|
@@ -33,11 +33,12 @@
|
|
33
33
|
require 'net/http'
|
34
34
|
|
35
35
|
module T2Server
|
36
|
+
# :stopdoc:
|
36
37
|
# An internal module to collect all the exceptions that we
|
37
38
|
# can't really do anything about ourselves, such as
|
38
39
|
# timeouts and lost connections. This is further wrapped
|
39
40
|
# and exposed in the API as T2Server::ConnectionError below.
|
40
|
-
module InternalHTTPError
|
41
|
+
module InternalHTTPError
|
41
42
|
end
|
42
43
|
|
43
44
|
# These are the HTTP errors we want to catch.
|
@@ -55,6 +56,7 @@ module T2Server
|
|
55
56
|
Net::ProtocolError
|
56
57
|
].each {|err| err.send(:include, InternalHTTPError)}
|
57
58
|
|
59
|
+
# :startdoc:
|
58
60
|
# This is a superclass for all T2Server exceptions. It is provided as a
|
59
61
|
# useful catch-all for all the internally raised/thrown exceptions.
|
60
62
|
class T2ServerError < RuntimeError
|
@@ -30,7 +30,8 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
require '
|
33
|
+
require 'rubygems'
|
34
|
+
require 'libxml'
|
34
35
|
|
35
36
|
module T2Server
|
36
37
|
|
@@ -44,6 +45,8 @@ module T2Server
|
|
44
45
|
# * Finished: The run has finished running and its outputs are available for
|
45
46
|
# download.
|
46
47
|
class Run
|
48
|
+
include LibXML
|
49
|
+
|
47
50
|
private_class_method :new
|
48
51
|
|
49
52
|
# The identifier of this run on the server. It is currently a UUID
|
@@ -134,18 +137,53 @@ module T2Server
|
|
134
137
|
end
|
135
138
|
|
136
139
|
# :call-seq:
|
137
|
-
# run.get_output(output) ->
|
138
|
-
#
|
139
|
-
# Return the
|
140
|
-
#
|
141
|
-
#
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
140
|
+
# run.get_output(output, refs=false) -> list
|
141
|
+
#
|
142
|
+
# Return the values of the workflow output port _output_. These are
|
143
|
+
# returned as a list of strings. If the output port represents a singleton
|
144
|
+
# output then a one item list is returned. By default this method returns
|
145
|
+
# the actual data from the output port but if _refs_ is set to true then
|
146
|
+
# it will instead return URIs to the actual data in the same list format.
|
147
|
+
# See also Run#get_output_refs.
|
148
|
+
def get_output(output, refs=false)
|
146
149
|
output.strip_path!
|
147
|
-
|
148
|
-
|
150
|
+
result = []
|
151
|
+
|
152
|
+
# look at the contents of the output port
|
153
|
+
lists, items = ls("out/#{output}")
|
154
|
+
|
155
|
+
# if lists and items are empty then it's a single value
|
156
|
+
if lists == [] and items == []
|
157
|
+
if refs
|
158
|
+
result << "#{@server.uri}/rest/runs/#{@uuid}/#{@links[:wdir]}/out/#{output}"
|
159
|
+
else
|
160
|
+
result << @server.get_run_attribute(@uuid, "#{@links[:wdir]}/out/#{output}")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# for each list recurse into it and add the items to the result
|
165
|
+
lists.each {|list| result << get_output("#{output}/#{list}", refs)}
|
166
|
+
|
167
|
+
# for each item, add it to the output list
|
168
|
+
items.each do |item|
|
169
|
+
if refs
|
170
|
+
result << "#{@server.uri}/rest/runs/#{@uuid}/#{@links[:wdir]}/out/#{output}/#{item}"
|
171
|
+
else
|
172
|
+
result << @server.get_run_attribute(@uuid, "#{@links[:wdir]}/out/#{output}/#{item}")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
result
|
177
|
+
end
|
178
|
+
|
179
|
+
# :call-seq:
|
180
|
+
# run.get_output_refs(output) -> list
|
181
|
+
#
|
182
|
+
# Return references (URIs) to the values of the workflow output port
|
183
|
+
# _output_. These are returned as a list of URIs. If the output port
|
184
|
+
# represents a singleton output then a one item list is returned.
|
185
|
+
def get_output_refs(output)
|
186
|
+
get_output(output, true)
|
149
187
|
end
|
150
188
|
|
151
189
|
# :call-seq:
|
@@ -355,19 +393,37 @@ module T2Server
|
|
355
393
|
# run.ls(dir="") -> [[dirs], [objects]]
|
356
394
|
#
|
357
395
|
# List a directory in the run's workspace on the server. If _dir_ is left
|
358
|
-
# blank then / is listed.
|
359
|
-
#
|
396
|
+
# blank then / is listed. As there is no concept of changing into a
|
397
|
+
# directory (_cd_) in Taverna Server then all paths passed into _ls_
|
398
|
+
# should be full paths starting at "root". The contents of a directory are
|
399
|
+
# returned as a list of two lists, "directories" and "objects"
|
400
|
+
# respectively. In the case of listing the contents of the "out"
|
401
|
+
# directory, the "directories" returned by _ls_ are actually output port
|
402
|
+
# names and their contents are the values held by these ports. If there
|
403
|
+
# are multiple values listed then that port represents a list. If there
|
404
|
+
# are further directories below a port name then it is a list of lists.
|
360
405
|
def ls(dir="")
|
361
406
|
dir.strip_path!
|
362
407
|
dir_list = @server.get_run_attribute(@uuid, "#{@links[:wdir]}/#{dir}")
|
363
|
-
doc = REXML::Document.new(dir_list)
|
364
408
|
|
365
409
|
# compile a list of directory entries stripping the
|
366
410
|
# directory name from the front of each filename
|
367
411
|
dirs = []
|
368
412
|
files = []
|
369
|
-
|
370
|
-
|
413
|
+
|
414
|
+
begin
|
415
|
+
doc = XML::Document.string(dir_list)
|
416
|
+
|
417
|
+
doc.find(XPaths::DIR, Namespaces::MAP).each {|e| dirs << e.content.split('/')[-1]}
|
418
|
+
doc.find(XPaths::FILE, Namespaces::MAP).each {|e| files << e.content.split('/')[-1]}
|
419
|
+
rescue XML::Error => xmle
|
420
|
+
# We expect to get a DOCUMENT_EMPTY error in some cases. All others
|
421
|
+
# should be re-raised.
|
422
|
+
if xmle.code != XML::Error::DOCUMENT_EMPTY
|
423
|
+
raise xmle
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
371
427
|
[dirs, files]
|
372
428
|
end
|
373
429
|
|
@@ -426,9 +482,9 @@ module T2Server
|
|
426
482
|
|
427
483
|
# get inputs
|
428
484
|
inputs = @server.get_run_attribute(@uuid, links[:inputs])
|
429
|
-
doc =
|
485
|
+
doc = XML::Document.string(inputs)
|
430
486
|
nsmap = Namespaces::MAP
|
431
|
-
links[:baclava] = "#{links[:inputs]}/" +
|
487
|
+
links[:baclava] = "#{links[:inputs]}/" + doc.find_first(XPaths::BACLAVA, nsmap).attributes["href"].split('/')[-1]
|
432
488
|
|
433
489
|
# set io properties
|
434
490
|
links[:io] = "#{links[:listeners]}/io"
|
@@ -440,20 +496,20 @@ module T2Server
|
|
440
496
|
end
|
441
497
|
|
442
498
|
def parse_description(desc)
|
443
|
-
doc =
|
499
|
+
doc = XML::Document.string(desc)
|
444
500
|
nsmap = Namespaces::MAP
|
445
501
|
{
|
446
|
-
:expiry =>
|
447
|
-
:workflow =>
|
448
|
-
:status =>
|
449
|
-
:createtime =>
|
450
|
-
:starttime =>
|
451
|
-
:finishtime =>
|
452
|
-
:wdir =>
|
453
|
-
:inputs =>
|
454
|
-
:output =>
|
455
|
-
:securectx =>
|
456
|
-
:listeners =>
|
502
|
+
:expiry => doc.find_first(XPaths::EXPIRY, nsmap).attributes["href"].split('/')[-1],
|
503
|
+
:workflow => doc.find_first(XPaths::WORKFLOW, nsmap).attributes["href"].split('/')[-1],
|
504
|
+
:status => doc.find_first(XPaths::STATUS, nsmap).attributes["href"].split('/')[-1],
|
505
|
+
:createtime => doc.find_first(XPaths::CREATETIME, nsmap).attributes["href"].split('/')[-1],
|
506
|
+
:starttime => doc.find_first(XPaths::STARTTIME, nsmap).attributes["href"].split('/')[-1],
|
507
|
+
:finishtime => doc.find_first(XPaths::FINISHTIME, nsmap).attributes["href"].split('/')[-1],
|
508
|
+
:wdir => doc.find_first(XPaths::WDIR, nsmap).attributes["href"].split('/')[-1],
|
509
|
+
:inputs => doc.find_first(XPaths::INPUTS, nsmap).attributes["href"].split('/')[-1],
|
510
|
+
:output => doc.find_first(XPaths::OUTPUT, nsmap).attributes["href"].split('/')[-1],
|
511
|
+
:securectx => doc.find_first(XPaths::SECURECTX, nsmap).attributes["href"].split('/')[-1],
|
512
|
+
:listeners => doc.find_first(XPaths::LISTENERS, nsmap).attributes["href"].split('/')[-1]
|
457
513
|
}
|
458
514
|
end
|
459
515
|
end
|
@@ -30,16 +30,19 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
+
require 'rubygems'
|
33
34
|
require 'base64'
|
34
35
|
require 'uri'
|
35
36
|
require 'net/https'
|
36
|
-
require '
|
37
|
+
require 'libxml'
|
37
38
|
|
38
39
|
module T2Server
|
39
40
|
|
40
41
|
# An interface for directly communicating with one or more Taverna 2 Server
|
41
42
|
# instances.
|
42
43
|
class Server
|
44
|
+
include LibXML
|
45
|
+
|
43
46
|
private_class_method :new
|
44
47
|
|
45
48
|
# The URI of this server instance as a String.
|
@@ -174,11 +177,17 @@ module T2Server
|
|
174
177
|
end
|
175
178
|
|
176
179
|
# :call-seq:
|
177
|
-
# server.delete_run(
|
180
|
+
# server.delete_run(run) -> bool
|
178
181
|
#
|
179
182
|
# Delete the specified run from the server, discarding all of its state.
|
180
|
-
|
181
|
-
|
183
|
+
# _run_ can be either a Run instance or a UUID.
|
184
|
+
def delete_run(run)
|
185
|
+
# get the uuid from the run if that is what is passed in
|
186
|
+
if run.instance_of? Run
|
187
|
+
run = run.uuid
|
188
|
+
end
|
189
|
+
|
190
|
+
request = Net::HTTP::Delete.new("#{@links[:runs]}/#{run}")
|
182
191
|
if ssl?
|
183
192
|
request.basic_auth @username, @password
|
184
193
|
end
|
@@ -191,12 +200,12 @@ module T2Server
|
|
191
200
|
case response
|
192
201
|
when Net::HTTPNoContent
|
193
202
|
# Success, carry on...
|
194
|
-
@runs.delete(
|
203
|
+
@runs.delete(run)
|
195
204
|
true
|
196
205
|
when Net::HTTPNotFound
|
197
|
-
raise RunNotFoundError.new(
|
206
|
+
raise RunNotFoundError.new(run)
|
198
207
|
when Net::HTTPForbidden
|
199
|
-
raise AccessForbiddenError.new("run #{
|
208
|
+
raise AccessForbiddenError.new("run #{run}")
|
200
209
|
when Net::HTTPUnauthorized
|
201
210
|
raise AuthorizationError.new(@username)
|
202
211
|
else
|
@@ -216,15 +225,21 @@ module T2Server
|
|
216
225
|
# :call-seq:
|
217
226
|
# server.set_run_input(run, input, value) -> bool
|
218
227
|
#
|
219
|
-
# Set the workflow input port _input_ on run _run_ to _value_.
|
228
|
+
# Set the workflow input port _input_ on run _run_ to _value_. _run_ can
|
229
|
+
# be either a Run instance or a UUID.
|
220
230
|
def set_run_input(run, input, value)
|
221
|
-
|
231
|
+
# get the run from the uuid if that is what is passed in
|
232
|
+
if not run.instance_of? Run
|
233
|
+
run = run(run)
|
234
|
+
end
|
235
|
+
|
236
|
+
path = "#{@links[:runs]}/#{run.run}/#{run.inputs}/input/#{input}"
|
222
237
|
set_attribute(path, Fragments::RUNINPUTVALUE % value, "application/xml")
|
223
238
|
rescue AttributeNotFoundError => e
|
224
|
-
if get_runs.has_key? uuid
|
239
|
+
if get_runs.has_key? run.uuid
|
225
240
|
raise e
|
226
241
|
else
|
227
|
-
raise RunNotFoundError.new(uuid)
|
242
|
+
raise RunNotFoundError.new(run.uuid)
|
228
243
|
end
|
229
244
|
end
|
230
245
|
|
@@ -232,26 +247,36 @@ module T2Server
|
|
232
247
|
# server.set_run_input_file(run, input, filename) -> bool
|
233
248
|
#
|
234
249
|
# Set the workflow input port _input_ on run _run_ to use the file at
|
235
|
-
# _filename_ for its input.
|
250
|
+
# _filename_ for its input. _run_ can be either a Run instance or a UUID.
|
236
251
|
def set_run_input_file(run, input, filename)
|
252
|
+
# get the run from the uuid if that is what is passed in
|
253
|
+
if not run.instance_of? Run
|
254
|
+
run = run(run)
|
255
|
+
end
|
256
|
+
|
237
257
|
path = "#{@links[:runs]}/#{run.uuid}/#{run.inputs}/input/#{input}"
|
238
258
|
set_attribute(path, Fragments::RUNINPUTFILE % filename, "application/xml")
|
239
259
|
rescue AttributeNotFoundError => e
|
240
|
-
if get_runs.has_key? uuid
|
260
|
+
if get_runs.has_key? run.uuid
|
241
261
|
raise e
|
242
262
|
else
|
243
|
-
raise RunNotFoundError.new(uuid)
|
263
|
+
raise RunNotFoundError.new(run.uuid)
|
244
264
|
end
|
245
265
|
end
|
246
266
|
|
247
267
|
# :call-seq:
|
248
|
-
# server.make_run_dir(
|
268
|
+
# server.make_run_dir(run, root, dir) -> bool
|
249
269
|
#
|
250
|
-
# Create a directory _dir_ within the directory _root_ on
|
251
|
-
#
|
252
|
-
def make_run_dir(
|
270
|
+
# Create a directory _dir_ within the directory _root_ on _run_. _run_ can
|
271
|
+
# be either a Run instance or a UUID. This is mainly for use by Run#mkdir.
|
272
|
+
def make_run_dir(run, root, dir)
|
273
|
+
# get the uuid from the run if that is what is passed in
|
274
|
+
if run.instance_of? Run
|
275
|
+
run = run.uuid
|
276
|
+
end
|
277
|
+
|
253
278
|
raise AccessForbiddenError.new("subdirectories (#{dir})") if dir.include? ?/
|
254
|
-
request = Net::HTTP::Post.new("#{@links[:runs]}/#{
|
279
|
+
request = Net::HTTP::Post.new("#{@links[:runs]}/#{run}/#{root}")
|
255
280
|
request.content_type = "application/xml"
|
256
281
|
if ssl?
|
257
282
|
request.basic_auth @username, @password
|
@@ -267,9 +292,9 @@ module T2Server
|
|
267
292
|
# OK, carry on...
|
268
293
|
true
|
269
294
|
when Net::HTTPNotFound
|
270
|
-
raise RunNotFoundError.new(
|
295
|
+
raise RunNotFoundError.new(run)
|
271
296
|
when Net::HTTPForbidden
|
272
|
-
raise AccessForbiddenError.new("#{dir} on run #{
|
297
|
+
raise AccessForbiddenError.new("#{dir} on run #{run}")
|
273
298
|
when Net::HTTPUnauthorized
|
274
299
|
raise AuthorizationError.new(@username)
|
275
300
|
else
|
@@ -278,14 +303,19 @@ module T2Server
|
|
278
303
|
end
|
279
304
|
|
280
305
|
# :call-seq:
|
281
|
-
# server.upload_run_file(
|
306
|
+
# server.upload_run_file(run, filename, location, rename) -> string
|
282
307
|
#
|
283
|
-
# Upload a file to
|
284
|
-
# by Run#upload_file.
|
285
|
-
def upload_run_file(
|
308
|
+
# Upload a file to _run_. _run_ can be either a Run instance or a UUID.
|
309
|
+
# Mainly for internal use by Run#upload_file.
|
310
|
+
def upload_run_file(run, filename, location, rename)
|
311
|
+
# get the uuid from the run if that is what is passed in
|
312
|
+
if run.instance_of? Run
|
313
|
+
run = run.uuid
|
314
|
+
end
|
315
|
+
|
286
316
|
contents = Base64.encode64(IO.read(filename))
|
287
317
|
rename = filename.split('/')[-1] if rename == ""
|
288
|
-
request = Net::HTTP::Post.new("#{@links[:runs]}/#{
|
318
|
+
request = Net::HTTP::Post.new("#{@links[:runs]}/#{run}/#{location}")
|
289
319
|
request.content_type = "application/xml"
|
290
320
|
if ssl?
|
291
321
|
request.basic_auth @username, @password
|
@@ -301,9 +331,9 @@ module T2Server
|
|
301
331
|
# Success, return remote name of uploaded file
|
302
332
|
rename
|
303
333
|
when Net::HTTPNotFound
|
304
|
-
raise RunNotFoundError.new(
|
334
|
+
raise RunNotFoundError.new(run)
|
305
335
|
when Net::HTTPForbidden
|
306
|
-
raise AccessForbiddenError.new("run #{
|
336
|
+
raise AccessForbiddenError.new("run #{run}")
|
307
337
|
when Net::HTTPUnauthorized
|
308
338
|
raise AuthorizationError.new(@username)
|
309
339
|
else
|
@@ -312,30 +342,42 @@ module T2Server
|
|
312
342
|
end
|
313
343
|
|
314
344
|
# :call-seq:
|
315
|
-
# server.get_run_attribute(
|
345
|
+
# server.get_run_attribute(run, path) -> string
|
316
346
|
#
|
317
|
-
# Get the attribute at _path_ in
|
318
|
-
|
319
|
-
|
347
|
+
# Get the attribute at _path_ in _run_. _run_ can be either a Run instance
|
348
|
+
# or a UUID.
|
349
|
+
def get_run_attribute(run, path)
|
350
|
+
# get the uuid from the run if that is what is passed in
|
351
|
+
if run.instance_of? Run
|
352
|
+
run = run.uuid
|
353
|
+
end
|
354
|
+
|
355
|
+
get_attribute("#{@links[:runs]}/#{run}/#{path}")
|
320
356
|
rescue AttributeNotFoundError => e
|
321
|
-
if get_runs.has_key?
|
357
|
+
if get_runs.has_key? run
|
322
358
|
raise e
|
323
359
|
else
|
324
|
-
raise RunNotFoundError.new(
|
360
|
+
raise RunNotFoundError.new(run)
|
325
361
|
end
|
326
362
|
end
|
327
363
|
|
328
364
|
# :call-seq:
|
329
|
-
# server.set_run_attribute(
|
365
|
+
# server.set_run_attribute(run, path, value) -> bool
|
330
366
|
#
|
331
|
-
# Set the attribute at _path_ in
|
332
|
-
|
333
|
-
|
367
|
+
# Set the attribute at _path_ in _run_ to _value_. _run_ can be either a
|
368
|
+
# Run instance or a UUID.
|
369
|
+
def set_run_attribute(run, path, value)
|
370
|
+
# get the uuid from the run if that is what is passed in
|
371
|
+
if run.instance_of? Run
|
372
|
+
run = run.uuid
|
373
|
+
end
|
374
|
+
|
375
|
+
set_attribute("#{@links[:runs]}/#{run}/#{path}", value, "text/plain")
|
334
376
|
rescue AttributeNotFoundError => e
|
335
|
-
if get_runs.has_key?
|
377
|
+
if get_runs.has_key? run
|
336
378
|
raise e
|
337
379
|
else
|
338
|
-
raise RunNotFoundError.new(
|
380
|
+
raise RunNotFoundError.new(run)
|
339
381
|
end
|
340
382
|
end
|
341
383
|
|
@@ -393,24 +435,24 @@ module T2Server
|
|
393
435
|
end
|
394
436
|
|
395
437
|
def parse_description(desc)
|
396
|
-
doc =
|
438
|
+
doc = XML::Document.string(desc)
|
397
439
|
nsmap = Namespaces::MAP
|
398
440
|
{
|
399
|
-
:runs => URI.parse(
|
400
|
-
:runlimit => URI.parse(
|
401
|
-
:permworkflows => URI.parse(
|
402
|
-
:permlisteners => URI.parse(
|
441
|
+
:runs => URI.parse(doc.find_first(XPaths::RUNS, nsmap).attributes["href"]).path,
|
442
|
+
:runlimit => URI.parse(doc.find_first(XPaths::RUNLIMIT, nsmap).attributes["href"]).path,
|
443
|
+
:permworkflows => URI.parse(doc.find_first(XPaths::PERMWKF, nsmap).attributes["href"]).path,
|
444
|
+
:permlisteners => URI.parse(doc.find_first(XPaths::PERMLSTN, nsmap).attributes["href"]).path
|
403
445
|
}
|
404
446
|
end
|
405
447
|
|
406
448
|
def get_runs
|
407
449
|
run_list = get_attribute("#{@links[:runs]}")
|
408
450
|
|
409
|
-
doc =
|
451
|
+
doc = XML::Document.string(run_list)
|
410
452
|
|
411
453
|
# get list of run uuids
|
412
454
|
uuids = []
|
413
|
-
|
455
|
+
doc.find(XPaths::RUN, Namespaces::MAP).each do |run|
|
414
456
|
uuids << run.attributes["href"].split('/')[-1]
|
415
457
|
end
|
416
458
|
|
@@ -30,7 +30,11 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
+
require 'rubygems'
|
34
|
+
require 'libxml'
|
35
|
+
|
33
36
|
module T2Server
|
37
|
+
# :stopdoc:
|
34
38
|
module Namespaces
|
35
39
|
SERVER = "http://ns.taverna.org.uk/2010/xml/server/"
|
36
40
|
REST = SERVER + "rest/"
|
@@ -39,7 +43,7 @@ module T2Server
|
|
39
43
|
"nsr" => Namespaces::REST
|
40
44
|
}
|
41
45
|
end
|
42
|
-
|
46
|
+
|
43
47
|
module Fragments
|
44
48
|
WORKFLOW = "<t2s:workflow xmlns:t2s=\"#{Namespaces::SERVER}\">\n %s\n</t2s:workflow>"
|
45
49
|
RUNINPUT = "<t2sr:runInput xmlns:t2sr=\"#{Namespaces::REST}\">\n %s\n</t2sr:runInput>"
|
@@ -48,4 +52,35 @@ module T2Server
|
|
48
52
|
UPLOAD = "<t2sr:upload xmlns:t2sr=\"#{Namespaces::REST}\" t2sr:name=\"%s\">\n %s\n</t2sr:upload>"
|
49
53
|
MKDIR = "<t2sr:mkdir xmlns:t2sr=\"#{Namespaces::REST}\" t2sr:name=\"%s\" />"
|
50
54
|
end
|
55
|
+
|
56
|
+
module XPaths
|
57
|
+
include LibXML
|
58
|
+
|
59
|
+
# Shut the libxml error handler up
|
60
|
+
XML::Error.set_handler(&XML::Error::QUIET_HANDLER)
|
61
|
+
|
62
|
+
# Server XPath queries
|
63
|
+
RUN = XML::XPath::Expression.new("//nsr:run")
|
64
|
+
RUNS = XML::XPath::Expression.new("//nsr:runs")
|
65
|
+
RUNLIMIT = XML::XPath::Expression.new("//nsr:runLimit")
|
66
|
+
PERMWKF = XML::XPath::Expression.new("//nsr:permittedWorkflows")
|
67
|
+
PERMLSTN = XML::XPath::Expression.new("//nsr:permittedListeners")
|
68
|
+
|
69
|
+
# Run XPath queries
|
70
|
+
DIR = XML::XPath::Expression.new("//nss:dir")
|
71
|
+
FILE = XML::XPath::Expression.new("//nss:file")
|
72
|
+
EXPIRY = XML::XPath::Expression.new("//nsr:expiry")
|
73
|
+
WORKFLOW = XML::XPath::Expression.new("//nsr:creationWorkflow")
|
74
|
+
STATUS = XML::XPath::Expression.new("//nsr:status")
|
75
|
+
CREATETIME = XML::XPath::Expression.new("//nsr:createTime")
|
76
|
+
STARTTIME = XML::XPath::Expression.new("//nsr:startTime")
|
77
|
+
FINISHTIME = XML::XPath::Expression.new("//nsr:finishTime")
|
78
|
+
WDIR = XML::XPath::Expression.new("//nsr:workingDirectory")
|
79
|
+
INPUTS = XML::XPath::Expression.new("//nsr:inputs")
|
80
|
+
OUTPUT = XML::XPath::Expression.new("//nsr:output")
|
81
|
+
SECURECTX = XML::XPath::Expression.new("//nsr:securityContext")
|
82
|
+
LISTENERS = XML::XPath::Expression.new("//nsr:listeners")
|
83
|
+
BACLAVA = XML::XPath::Expression.new("//nsr:baclava")
|
84
|
+
end
|
85
|
+
# :startdoc:
|
51
86
|
end
|
data/lib/t2server.rb
CHANGED
@@ -30,42 +30,6 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
|
34
|
-
require
|
35
|
-
require '
|
36
|
-
require 't2server/run'
|
37
|
-
|
38
|
-
# This is a Ruby library to interface with the Taverna 2 Server REST API.
|
39
|
-
#
|
40
|
-
# There are two API entry points:
|
41
|
-
# * T2Server::Run - Use this for running single jobs on a server.
|
42
|
-
# * T2Server::Server - Use this if you are providing a web interface to a
|
43
|
-
# Taverna 2 Server instance.
|
44
|
-
module T2Server
|
45
|
-
# The version of this library
|
46
|
-
GEM_VERSION = "0.2.1"
|
47
|
-
# The version of the Taverna 2 Server API that this library can interface with
|
48
|
-
API_VERSION = "2.2a1"
|
49
|
-
end
|
50
|
-
|
51
|
-
# Add methods to the String class to operate on file paths.
|
52
|
-
class String
|
53
|
-
# :call-seq:
|
54
|
-
# str.strip_path -> string
|
55
|
-
#
|
56
|
-
# Returns a new String with one leading and one trailing slash
|
57
|
-
# removed from the ends of _str_ (if present).
|
58
|
-
def strip_path
|
59
|
-
self.gsub(/^\//, "").chomp("/")
|
60
|
-
end
|
61
|
-
|
62
|
-
# :call-seq:
|
63
|
-
# str.strip_path! -> str or nil
|
64
|
-
#
|
65
|
-
# Modifies _str_ in place as described for String#strip_path,
|
66
|
-
# returning _str_, or returning +nil+ if no modifications were made.
|
67
|
-
def strip_path!
|
68
|
-
g = self.gsub!(/^\//, "")
|
69
|
-
self.chomp!("/") || g
|
70
|
-
end
|
71
|
-
end
|
33
|
+
# This is simply here to provide backwards compatibility. Old versions had an
|
34
|
+
# inconsistancy between the gem name and the file to require to use it.
|
35
|
+
require 't2-server'
|
data/test/tc_paths.rb
CHANGED
data/test/tc_run.rb
CHANGED
@@ -30,7 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
-
require '
|
33
|
+
require 't2-server'
|
34
34
|
|
35
35
|
class TestRun < Test::Unit::TestCase
|
36
36
|
|
@@ -41,9 +41,6 @@ class TestRun < Test::Unit::TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# test bad state code
|
44
|
-
assert_raise(T2Server::RunStateError) do
|
45
|
-
@run.get_output("out")
|
46
|
-
end
|
47
44
|
assert_raise(T2Server::RunStateError) do
|
48
45
|
@run.wait
|
49
46
|
end
|
@@ -61,7 +58,7 @@ class TestRun < Test::Unit::TestCase
|
|
61
58
|
|
62
59
|
# exitcode and output
|
63
60
|
assert_instance_of(Fixnum, @run.exitcode)
|
64
|
-
assert_equal(@run.get_output("Message"), "Hello, World!")
|
61
|
+
assert_equal(@run.get_output("Message"), ["Hello, World!"])
|
65
62
|
assert_raise(T2Server::AccessForbiddenError) do
|
66
63
|
@run.get_output("wrong!")
|
67
64
|
end
|
data/test/tc_server.rb
CHANGED
data/test/ts_t2server.rb
CHANGED
@@ -31,10 +31,13 @@
|
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
33
|
require 'test/unit'
|
34
|
-
require '
|
34
|
+
require 't2-server'
|
35
35
|
|
36
36
|
# get a server address to test - 30 second timeout
|
37
|
-
print "\nPlease supply a valid Taverna 2 Server address
|
37
|
+
print "\nPlease supply a valid Taverna 2 Server address.\n\nNOTE that these " +
|
38
|
+
"tests will fully load the server and then delete all the runs that it " +
|
39
|
+
"has permission to do so - if you are not using security ALL runs will be " +
|
40
|
+
"deleted!\n(leave blank to skip tests): "
|
38
41
|
$stdout.flush
|
39
42
|
if select([$stdin], [], [], 30)
|
40
43
|
$address = $stdin.gets.chomp
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: t2-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Robert Haines
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-22 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -34,24 +34,43 @@ dependencies:
|
|
34
34
|
version: 0.8.7
|
35
35
|
type: :development
|
36
36
|
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: libxml-ruby
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 27
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 1
|
49
|
+
- 4
|
50
|
+
version: 1.1.4
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
37
53
|
description: This gem provides access to the Taverna 2 Server REST interface from Ruby.
|
38
54
|
email: rhaines@manchester.ac.uk
|
39
|
-
executables:
|
40
|
-
|
55
|
+
executables:
|
56
|
+
- t2-delete-runs
|
57
|
+
- t2-run-workflow
|
58
|
+
- t2-server-info
|
41
59
|
extensions: []
|
42
60
|
|
43
61
|
extra_rdoc_files:
|
44
62
|
- README.rdoc
|
45
63
|
- LICENCE
|
46
64
|
files:
|
47
|
-
- bin/
|
48
|
-
- bin/
|
49
|
-
- bin/
|
65
|
+
- bin/t2-server-info
|
66
|
+
- bin/t2-delete-runs
|
67
|
+
- bin/t2-run-workflow
|
50
68
|
- lib/t2server.rb
|
51
|
-
- lib/
|
52
|
-
- lib/
|
53
|
-
- lib/
|
54
|
-
- lib/
|
69
|
+
- lib/t2-server/server.rb
|
70
|
+
- lib/t2-server/exceptions.rb
|
71
|
+
- lib/t2-server/xml.rb
|
72
|
+
- lib/t2-server/run.rb
|
73
|
+
- lib/t2-server.rb
|
55
74
|
- test/tc_server.rb
|
56
75
|
- test/tc_paths.rb
|
57
76
|
- test/tc_run.rb
|
@@ -64,8 +83,10 @@ homepage: http://www.taverna.org.uk/
|
|
64
83
|
licenses: []
|
65
84
|
|
66
85
|
post_install_message:
|
67
|
-
rdoc_options:
|
68
|
-
|
86
|
+
rdoc_options:
|
87
|
+
- -N
|
88
|
+
- --tab-width=2
|
89
|
+
- --main=README.rdoc
|
69
90
|
require_paths:
|
70
91
|
- lib
|
71
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|