rbbt-util 3.2.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +65 -0
- data/bin/run_workflow.rb +142 -69
- data/lib/rbbt-util.rb +3 -3
- data/lib/rbbt.rb +12 -3
- data/lib/rbbt/annotations.rb +215 -0
- data/lib/rbbt/{util/fix_width_table.rb → fix_width_table.rb} +17 -13
- data/lib/rbbt/persist.rb +164 -0
- data/lib/rbbt/persist/tsv.rb +135 -0
- data/lib/rbbt/resource.rb +100 -0
- data/lib/rbbt/resource/path.rb +180 -0
- data/lib/rbbt/resource/rake.rb +48 -0
- data/lib/rbbt/resource/util.rb +111 -0
- data/lib/rbbt/resource/with_key.rb +28 -0
- data/lib/rbbt/tsv.rb +134 -0
- data/lib/rbbt/tsv/accessor.rb +345 -0
- data/lib/rbbt/tsv/attach.rb +183 -0
- data/lib/rbbt/tsv/attach/util.rb +277 -0
- data/lib/rbbt/{util/tsv/filters.rb → tsv/filter.rb} +76 -37
- data/lib/rbbt/tsv/index.rb +453 -0
- data/lib/rbbt/tsv/manipulate.rb +361 -0
- data/lib/rbbt/tsv/parser.rb +231 -0
- data/lib/rbbt/tsv/serializers.rb +79 -0
- data/lib/rbbt/tsv/util.rb +67 -0
- data/lib/rbbt/util/R.rb +3 -3
- data/lib/rbbt/util/chain_methods.rb +64 -0
- data/lib/rbbt/util/cmd.rb +17 -13
- data/lib/rbbt/util/excel2tsv.rb +4 -3
- data/lib/rbbt/util/log.rb +1 -0
- data/lib/rbbt/util/misc.rb +296 -285
- data/lib/rbbt/util/open.rb +9 -2
- data/lib/rbbt/util/persistence.rb +1 -1
- data/lib/rbbt/util/task/job.rb +3 -1
- data/lib/rbbt/workflow.rb +193 -0
- data/lib/rbbt/workflow/accessor.rb +249 -0
- data/lib/rbbt/workflow/annotate.rb +60 -0
- data/lib/rbbt/workflow/soap.rb +100 -0
- data/lib/rbbt/workflow/step.rb +102 -0
- data/lib/rbbt/workflow/task.rb +76 -0
- data/test/rbbt/resource/test_path.rb +12 -0
- data/test/rbbt/test_annotations.rb +106 -0
- data/test/rbbt/{util/test_fix_width_table.rb → test_fix_width_table.rb} +8 -9
- data/test/rbbt/test_resource.rb +66 -0
- data/test/rbbt/test_tsv.rb +332 -0
- data/test/rbbt/test_workflow.rb +102 -0
- data/test/rbbt/tsv/test_accessor.rb +163 -0
- data/test/rbbt/{util/tsv → tsv}/test_attach.rb +86 -43
- data/test/rbbt/{util/tsv/test_filters.rb → tsv/test_filter.rb} +31 -13
- data/test/rbbt/tsv/test_index.rb +284 -0
- data/test/rbbt/{util/tsv → tsv}/test_manipulate.rb +35 -105
- data/test/rbbt/util/test_R.rb +1 -1
- data/test/rbbt/util/test_chain_methods.rb +22 -0
- data/test/rbbt/util/test_filecache.rb +0 -1
- data/test/rbbt/util/test_misc.rb +97 -79
- data/test/rbbt/util/test_open.rb +1 -0
- data/test/rbbt/util/test_tmpfile.rb +1 -1
- data/test/rbbt/workflow/test_soap.rb +103 -0
- data/test/rbbt/workflow/test_step.rb +142 -0
- data/test/rbbt/workflow/test_task.rb +84 -0
- data/test/test_helper.rb +7 -7
- metadata +80 -54
- data/lib/rbbt/util/rake.rb +0 -176
- data/lib/rbbt/util/resource.rb +0 -355
- data/lib/rbbt/util/task.rb +0 -183
- data/lib/rbbt/util/tc_hash.rb +0 -324
- data/lib/rbbt/util/tsv.rb +0 -236
- data/lib/rbbt/util/tsv/accessor.rb +0 -312
- data/lib/rbbt/util/tsv/attach.rb +0 -416
- data/lib/rbbt/util/tsv/index.rb +0 -419
- data/lib/rbbt/util/tsv/manipulate.rb +0 -300
- data/lib/rbbt/util/tsv/misc.rb +0 -41
- data/lib/rbbt/util/tsv/parse.rb +0 -324
- data/lib/rbbt/util/tsv/resource.rb +0 -88
- data/lib/rbbt/util/workflow.rb +0 -135
- data/lib/rbbt/util/workflow/soap.rb +0 -116
- data/test/rbbt/util/test_persistence.rb +0 -201
- data/test/rbbt/util/test_rake.rb +0 -54
- data/test/rbbt/util/test_resource.rb +0 -77
- data/test/rbbt/util/test_task.rb +0 -133
- data/test/rbbt/util/test_tc_hash.rb +0 -144
- data/test/rbbt/util/test_tsv.rb +0 -221
- data/test/rbbt/util/test_workflow.rb +0 -135
- data/test/rbbt/util/tsv/test_accessor.rb +0 -150
- data/test/rbbt/util/tsv/test_index.rb +0 -241
- data/test/rbbt/util/tsv/test_parse.rb +0 -87
- data/test/rbbt/util/tsv/test_resource.rb +0 -9
@@ -0,0 +1,60 @@
|
|
1
|
+
module AnnotatedModule
|
2
|
+
def self.extended(base)
|
3
|
+
if not base.respond_to? :inputs
|
4
|
+
class << base
|
5
|
+
attr_accessor :description, :inputs, :input_types, :input_descriptions, :input_defaults
|
6
|
+
|
7
|
+
def description
|
8
|
+
i = @description; @description = ""; i
|
9
|
+
end
|
10
|
+
|
11
|
+
def inputs
|
12
|
+
i = @inputs; @inputs = []; i
|
13
|
+
end
|
14
|
+
|
15
|
+
def input_types
|
16
|
+
i = @input_types; @input_types = {}; i
|
17
|
+
end
|
18
|
+
|
19
|
+
def input_descriptions
|
20
|
+
i = @input_descriptions; @input_descriptions = {}; i
|
21
|
+
end
|
22
|
+
|
23
|
+
def input_defaults
|
24
|
+
i = @input_defaults; @input_defaults = {}; i
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
i = @description; @description = ""; i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
base.description = ""
|
33
|
+
base.inputs = []
|
34
|
+
base.input_types = {}
|
35
|
+
base.input_descriptions = {}
|
36
|
+
base.input_defaults = {}
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def desc(description)
|
42
|
+
@description = description
|
43
|
+
end
|
44
|
+
|
45
|
+
def dep(*dependencies, &block)
|
46
|
+
dependencies << block if block_given?
|
47
|
+
@dependencies.concat dependencies
|
48
|
+
end
|
49
|
+
|
50
|
+
def input(name, type = nil, desc = nil, default = nil)
|
51
|
+
name = name.to_sym
|
52
|
+
type = type.to_sym
|
53
|
+
@inputs << name
|
54
|
+
@input_types[name] = type unless type.nil?
|
55
|
+
@input_descriptions[name] = desc unless desc.nil?
|
56
|
+
@input_defaults[name] = default unless default.nil?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'simplews'
|
3
|
+
|
4
|
+
class WorkflowSOAP < SimpleWS
|
5
|
+
attr_accessor :workflow
|
6
|
+
def job(jobid)
|
7
|
+
workdir = @workflow.workdir
|
8
|
+
if workdir.respond_to? :find
|
9
|
+
workdir_find = workdir.find
|
10
|
+
else
|
11
|
+
workdir_find = workdir
|
12
|
+
end
|
13
|
+
|
14
|
+
@workflow.load(File.join(workdir_find, jobid))
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(workflow, *args)
|
18
|
+
super(workflow.to_s,*args)
|
19
|
+
@workflow = workflow
|
20
|
+
@workflow.synchronous_exports.each do |name| synchronous name end
|
21
|
+
@workflow.asynchronous_exports.each do |name| asynchronous name end
|
22
|
+
|
23
|
+
desc "Job management: Check the status of a job"
|
24
|
+
param_desc :jobid => "Job identifier", :return => "Status code. Special status codes are: 'done' and 'error'"
|
25
|
+
serve :status, [:jobid], :jobid => :string, :return => :string do |jobid|
|
26
|
+
(job(jobid).status || :queued).to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Job management: Return an array with the messages issued by the job"
|
30
|
+
param_desc :jobid => "Job identifier", :return => "Array with message strings"
|
31
|
+
serve :messages, ['jobid'], :job => :string, :return => :array do |jobid|
|
32
|
+
job(jobid).messages || []
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Job management: Return a YAML string containing arbitrary information set up by the job"
|
36
|
+
param_desc :jobid => "Job identifier", :return => "Hash with arbitrary values in YAML format"
|
37
|
+
serve :info, ['jobid'], :jobid => :string, :return => :string do |jobid|
|
38
|
+
job(jobid).info.to_yaml
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Job management: Abort the job"
|
42
|
+
param_desc :jobid => "Job identifier"
|
43
|
+
serve :abort, %w(jobid), :jobid => :string, :return => false do |jobid|
|
44
|
+
job(jobid).abort
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Job management: Check if the job is done. Could have finished successfully, with error, or have been aborted"
|
48
|
+
param_desc :jobid => "Job identifier", :return => "True if the job has status 'done', 'error' or 'aborted'"
|
49
|
+
serve :done, %w(jobid), :jobid => :string, :return => :boolean do |jobid|
|
50
|
+
[:done, :error, :aborted].include?((job(jobid).status || :queued).to_sym)
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Job management: Check if the job has finished with error. The last message is the error message"
|
54
|
+
param_desc :jobid => "Job identifier", :return => "True if the job has status 'error'"
|
55
|
+
serve :error, %w(jobid), :jobid => :string, :return => :boolean do |jobid|
|
56
|
+
job(jobid).status.to_sym == :error
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Job management: Load job result as string "
|
60
|
+
param_desc :jobid => "Job identifier", :return => "String containing the result of the job"
|
61
|
+
serve :load_string, %w(jobid), :jobid => :string, :return => :string do |jobid|
|
62
|
+
job(jobid).load.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def synchronous(*tasknames)
|
67
|
+
tasknames.each do |name|
|
68
|
+
task = @workflow.tasks[name]
|
69
|
+
desc @workflow.task_description[name] if @workflow.task_description.include? name
|
70
|
+
|
71
|
+
rec_inputs = @workflow.rec_inputs name
|
72
|
+
rec_input_descriptions= @workflow.rec_input_descriptions name
|
73
|
+
rec_input_types= @workflow.rec_input_types name
|
74
|
+
|
75
|
+
param_desc rec_input_descriptions
|
76
|
+
serve name, rec_inputs, rec_input_types, &task
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def asynchronous(*tasknames)
|
81
|
+
tasknames.each do |name|
|
82
|
+
task = @workflow.tasks[name]
|
83
|
+
desc @workflow.task_description[name] if @workflow.task_description.include? name
|
84
|
+
|
85
|
+
rec_inputs = @workflow.rec_inputs name
|
86
|
+
rec_input_descriptions= @workflow.rec_input_descriptions name
|
87
|
+
rec_input_types= @workflow.rec_input_types name
|
88
|
+
|
89
|
+
param_desc rec_input_descriptions.merge(:suggested_name => "Suggested Name", :return => "Job identifier")
|
90
|
+
serve name, [:suggested_name] + rec_inputs, rec_input_types.merge(:suggested_name => :string, :return => :string) do |jobname, *inputs|
|
91
|
+
inputs = Hash[*@workflow.rec_inputs(name).zip(inputs).flatten]
|
92
|
+
|
93
|
+
step = @workflow.job(name, jobname, inputs)
|
94
|
+
step.fork
|
95
|
+
@workflow.id_for step.path
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'rbbt/persist'
|
2
|
+
require 'rbbt/persist/tsv'
|
3
|
+
require 'rbbt/util/log'
|
4
|
+
require 'rbbt/workflow/accessor'
|
5
|
+
|
6
|
+
class Step
|
7
|
+
attr_accessor :path, :task, :inputs, :dependencies
|
8
|
+
attr_accessor :pid
|
9
|
+
|
10
|
+
class Aborted < Exception; end
|
11
|
+
|
12
|
+
def initialize(path, task = nil, inputs = nil, dependencies = nil)
|
13
|
+
@path = path
|
14
|
+
@task = task
|
15
|
+
@dependencies = case
|
16
|
+
when dependencies.nil?
|
17
|
+
[]
|
18
|
+
when Array === dependencies
|
19
|
+
dependencies
|
20
|
+
else
|
21
|
+
[dependencies]
|
22
|
+
end
|
23
|
+
@inputs = inputs || []
|
24
|
+
end
|
25
|
+
|
26
|
+
def exec
|
27
|
+
@task.exec_in self, *@inputs
|
28
|
+
end
|
29
|
+
|
30
|
+
def join
|
31
|
+
if @pid.nil?
|
32
|
+
while not done? do
|
33
|
+
Log.debug "Waiting: #{info[:step]}"
|
34
|
+
sleep 5
|
35
|
+
end
|
36
|
+
else
|
37
|
+
Process.waitpid @pid
|
38
|
+
@pid = nil
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
Persist.persist "Job", @task.result_type, :file => @path, :check => rec_dependencies.collect{|dependency| dependency.path}.uniq do
|
45
|
+
log task.name, "Starting task: #{ name }"
|
46
|
+
set_info :dependencies, @dependencies.collect{|dep| [dep.task.name, dep.name]}
|
47
|
+
@dependencies.each{|dependency| dependency.run}
|
48
|
+
set_info :status, :start
|
49
|
+
set_info :inputs, Misc.zip2hash(task.inputs, @inputs) unless task.inputs.nil?
|
50
|
+
res = exec
|
51
|
+
set_info :status, :done
|
52
|
+
res
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def fork
|
57
|
+
raise "Can not fork: Step is waiting for proces #{@pid} to finish" if not @pid.nil?
|
58
|
+
@pid = Process.fork do
|
59
|
+
begin
|
60
|
+
trap(:INT) { raise Step::Aborted.new "INT signal recieved" }
|
61
|
+
run
|
62
|
+
rescue Exception
|
63
|
+
log(:error, "#{$!.class}: #{$!.message}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
set_info :pid, @pid
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def abort
|
71
|
+
if @pid.nil?
|
72
|
+
false
|
73
|
+
else
|
74
|
+
Process.kill("INT", @pid)
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def load
|
80
|
+
raise "Can not load: Step is waiting for proces #{@pid} to finish" if not done?
|
81
|
+
Persist.persist "Job", @task.result_type, :file => @path, :check => rec_dependencies.collect{|dependency| dependency.path} do
|
82
|
+
exec
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def clean
|
87
|
+
if File.exists?(path) or File.exists?(info_file)
|
88
|
+
begin
|
89
|
+
FileUtils.rm info_file
|
90
|
+
FileUtils.rm path
|
91
|
+
FileUtils.rm_rf files_dir
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def rec_dependencies
|
97
|
+
@dependencies.collect{|step| step.rec_dependencies}.flatten.concat @dependencies
|
98
|
+
end
|
99
|
+
def step(name)
|
100
|
+
rec_dependencies.select{|step| step.task.name.to_sym == name.to_sym}.first
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rbbt/util/misc'
|
2
|
+
require 'rbbt/persist'
|
3
|
+
|
4
|
+
module Task
|
5
|
+
attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :description, :name
|
6
|
+
|
7
|
+
def self.setup(options = {}, &block)
|
8
|
+
block.extend Task
|
9
|
+
options = IndiferentHash.setup options
|
10
|
+
block.singleton_methods.
|
11
|
+
select{|method| method.to_s[-1] != "="[0]}.each{|method|
|
12
|
+
if block.respond_to?(method + "=") and options.include? method.to_sym
|
13
|
+
block.send(method + '=', options[method.to_sym])
|
14
|
+
end
|
15
|
+
}
|
16
|
+
block
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_description
|
20
|
+
if description =~ /\n\n/
|
21
|
+
short_description, rest = description.match(/(.*?)\n\n(.*)/).values_at 1, 2
|
22
|
+
else
|
23
|
+
short_description = description
|
24
|
+
rest = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
if rest.nil?
|
28
|
+
long_description = ""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def param_options
|
33
|
+
end
|
34
|
+
|
35
|
+
def take_input_values(input_values)
|
36
|
+
return [] if @inputs.nil?
|
37
|
+
values = []
|
38
|
+
@inputs.each do |input|
|
39
|
+
value = input_values[input] ||
|
40
|
+
IndiferentHash.setup(@input_defaults || {})[input]
|
41
|
+
values << value
|
42
|
+
end
|
43
|
+
values
|
44
|
+
end
|
45
|
+
|
46
|
+
def exec(*args)
|
47
|
+
case
|
48
|
+
when (args.length == 1 and not inputs.nil? and inputs.length > 1 and Hash === args.first)
|
49
|
+
self.call *take_input_values(IndiferentHash.setup(args.first))
|
50
|
+
else
|
51
|
+
self.call *args
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def exec_in(object, *args)
|
56
|
+
case
|
57
|
+
when (args.length == 1 and not inputs.nil? and inputs.length > 1 and Hash === args.first)
|
58
|
+
object.instance_exec *IndiferentHash.setup(args.first).values_at(*inputs), &self
|
59
|
+
else
|
60
|
+
object.instance_exec *args, &self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def persist_exec(filename, *args)
|
65
|
+
Persist.persist "Task", @persistence_type, :file => filename do
|
66
|
+
exec *args
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def persist_exec_in(filename, *args)
|
71
|
+
Persist.persist "Task", @persistence_type, :file => filename do
|
72
|
+
exec_in *args
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '../../../test_helper')
|
2
|
+
require 'rbbt/resource/path'
|
3
|
+
require 'rbbt/util/tmpfile'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class TestTSV < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_prev
|
9
|
+
path = Path.setup "/tmp"
|
10
|
+
assert_equal "/tmp/bar/foo", path.foo("bar")
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
require 'rbbt/annotations'
|
3
|
+
require 'rbbt/util/tmpfile'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
module AnnotatedString
|
7
|
+
extend Annotation
|
8
|
+
self.annotation :annotation_str
|
9
|
+
|
10
|
+
def add_annot
|
11
|
+
self + annotation_str
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module AnnotatedString2
|
16
|
+
extend Annotation
|
17
|
+
include AnnotatedString
|
18
|
+
self.annotation :annotation_str2
|
19
|
+
end
|
20
|
+
|
21
|
+
class TestAnnotations < Test::Unit::TestCase
|
22
|
+
|
23
|
+
def test_annotated_string
|
24
|
+
assert_equal %w(annotation_str), AnnotatedString.annotations.collect{|a| a.to_s}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_string
|
28
|
+
str = "string"
|
29
|
+
annotation_str = "Annotation String"
|
30
|
+
AnnotatedString.setup(str, annotation_str)
|
31
|
+
assert_equal [AnnotatedString], str.annotation_types
|
32
|
+
assert_equal annotation_str, str.annotation_str
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_array
|
36
|
+
ary = ["string"]
|
37
|
+
annotation_str = "Annotation String"
|
38
|
+
AnnotatedArray.setup_chain(ary)
|
39
|
+
AnnotatedString.setup(ary, annotation_str)
|
40
|
+
assert_equal [AnnotatedString], ary.annotation_types
|
41
|
+
assert_equal annotation_str, ary.annotation_str
|
42
|
+
assert_equal annotation_str, ary[0].annotation_str
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_info
|
46
|
+
ary = ["string"]
|
47
|
+
annotation_str = "Annotation String"
|
48
|
+
AnnotatedString.setup(ary, annotation_str)
|
49
|
+
assert_equal({:annotation_str => annotation_str, :annotation_types => [AnnotatedString]}, ary.info)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_load
|
53
|
+
str = "string"
|
54
|
+
annotation_str = "Annotation String"
|
55
|
+
info = {:annotation_str => annotation_str, :annotation_types => [AnnotatedString]}
|
56
|
+
|
57
|
+
Annotated.load(str, info)
|
58
|
+
assert_equal annotation_str, str.annotation_str
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_tsv
|
62
|
+
str1 = "string1"
|
63
|
+
annotation_str1 = "Annotation String 1"
|
64
|
+
str2 = "string2"
|
65
|
+
annotation_str2 = "Annotation String 2"
|
66
|
+
AnnotatedString.setup(str1, annotation_str1)
|
67
|
+
AnnotatedString.setup(str2, annotation_str2)
|
68
|
+
assert_equal str1, Annotated.tsv([str1, str2], :all)[str1.id]["literal"]
|
69
|
+
assert_equal annotation_str1, Annotated.tsv([str1, str2], :annotation_str, :JSON)[str1.id]["annotation_str"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_literal
|
73
|
+
str = "string"
|
74
|
+
annotation_str = "Annotation String"
|
75
|
+
AnnotatedString.setup(str, annotation_str)
|
76
|
+
assert_equal ["string"], str.tsv_values("literal")
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_load_tsv
|
80
|
+
str1 = "string1"
|
81
|
+
annotation_str1 = "Annotation String 1"
|
82
|
+
str2 = "string2"
|
83
|
+
annotation_str2 = "Annotation String 2"
|
84
|
+
AnnotatedString.setup(str1, annotation_str1)
|
85
|
+
AnnotatedString.setup(str2, annotation_str2)
|
86
|
+
assert_equal annotation_str1, Annotated.load_tsv(Annotated.tsv([str1, str2], :all)).sort.first.annotation_str
|
87
|
+
assert_equal str1, Annotated.load_tsv(Annotated.tsv([str1, str2], :literal, :JSON)).sort.first
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_inheritance
|
91
|
+
str = "string1"
|
92
|
+
annotation_str1 = "Annotation String 1"
|
93
|
+
annotation_str2 = "Annotation String 2"
|
94
|
+
assert_equal [AnnotatedString], AnnotatedString2.inheritance
|
95
|
+
AnnotatedString2.setup(str, annotation_str1, annotation_str2)
|
96
|
+
assert_equal annotation_str1, str.annotation_str
|
97
|
+
assert_equal annotation_str2, str.annotation_str2
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_annotation_methods
|
101
|
+
str = "string"
|
102
|
+
annotation_str = "Annotation String"
|
103
|
+
AnnotatedString.setup(str, annotation_str)
|
104
|
+
assert_equal str + annotation_str, str.add_annot
|
105
|
+
end
|
106
|
+
end
|