rbbt-util 3.2.1 → 4.0.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 +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
|