scout-gear 10.7.2 → 10.7.4
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.
- checksums.yaml +4 -4
- data/.vimproject +47 -32
- data/VERSION +1 -1
- data/bin/scout +15 -2
- data/lib/scout/association/index.rb +4 -0
- data/lib/scout/association/item.rb +1 -1
- data/lib/scout/association.rb +32 -10
- data/lib/scout/entity/identifiers.rb +2 -2
- data/lib/scout/entity/property.rb +2 -2
- data/lib/scout/knowledge_base/enrichment.rb +9 -0
- data/lib/scout/knowledge_base/entity.rb +152 -0
- data/lib/scout/knowledge_base/list.rb +95 -0
- data/lib/scout/knowledge_base/query.rb +96 -0
- data/lib/scout/knowledge_base/registry.rb +175 -0
- data/lib/scout/knowledge_base/traverse.rb +329 -0
- data/lib/scout/knowledge_base.rb +91 -0
- data/lib/scout/persist/engine/tokyocabinet.rb +85 -77
- data/lib/scout/persist/tsv/adapter/base.rb +8 -22
- data/lib/scout/tsv/annotation.rb +4 -4
- data/lib/scout/tsv/index.rb +0 -2
- data/lib/scout/tsv/parser.rb +11 -1
- data/lib/scout/tsv/stream.rb +3 -3
- data/lib/scout/tsv/transformer.rb +12 -0
- data/lib/scout/tsv/util/process.rb +2 -2
- data/lib/scout/tsv.rb +2 -0
- data/lib/scout/workflow/definition.rb +6 -2
- data/lib/scout/workflow/deployment/trace.rb +1 -1
- data/lib/scout/workflow/step/dependencies.rb +3 -6
- data/lib/scout/workflow/step/info.rb +17 -3
- data/lib/scout/workflow/task/info.rb +99 -0
- data/lib/scout/workflow/task.rb +1 -0
- data/scout-gear.gemspec +27 -7
- data/scout_commands/doc +3 -3
- data/scout_commands/kb/config +33 -0
- data/scout_commands/kb/entities +35 -0
- data/scout_commands/kb/list +39 -0
- data/scout_commands/{db → kb}/query +6 -11
- data/scout_commands/{db → kb}/register +9 -8
- data/scout_commands/{db → kb}/show +6 -16
- data/scout_commands/kb/traverse +66 -0
- data/scout_commands/workflow/task +7 -2
- data/test/data/person/brothers +1 -1
- data/test/scout/entity/test_identifiers.rb +3 -3
- data/test/scout/knowledge_base/test_enrichment.rb +0 -0
- data/test/scout/knowledge_base/test_entity.rb +38 -0
- data/test/scout/knowledge_base/test_list.rb +40 -0
- data/test/scout/knowledge_base/test_query.rb +39 -0
- data/test/scout/knowledge_base/test_registry.rb +35 -0
- data/test/scout/knowledge_base/test_traverse.rb +245 -0
- data/test/scout/persist/test_tsv.rb +1 -0
- data/test/scout/test_association.rb +32 -3
- data/test/scout/test_entity.rb +0 -15
- data/test/scout/test_knowledge_base.rb +27 -0
- data/test/scout/test_tsv.rb +15 -0
- data/test/scout/tsv/test_parser.rb +4 -0
- data/test/scout/tsv/test_transformer.rb +13 -0
- data/test/scout/workflow/step/test_info.rb +11 -0
- data/test/scout/workflow/task/test_info.rb +22 -0
- data/test/test_helper.rb +17 -0
- metadata +26 -9
@@ -1,105 +1,112 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
if String === tokyocabinet_class && tokyocabinet_class.include?(":big")
|
9
|
-
big = true
|
10
|
-
tokyocabinet_class = tokyocabinet_class.split(":").first
|
11
|
-
else
|
12
|
-
big = false
|
13
|
-
end
|
1
|
+
begin
|
2
|
+
require 'tokyocabinet'
|
3
|
+
continue = true
|
4
|
+
rescue Exception
|
5
|
+
Log.warn "The Tokyocabinet gem could not be loaded: TSV persistence may not work"
|
6
|
+
continue = false
|
7
|
+
end
|
14
8
|
|
15
|
-
|
16
|
-
|
9
|
+
if continue
|
10
|
+
module ScoutCabinet
|
11
|
+
attr_accessor :persistence_path, :persistence_class
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
def self.open(path, write = true, tokyocabinet_class = TokyoCabinet::HDB)
|
14
|
+
path = path.find if Path === path
|
15
|
+
if String === tokyocabinet_class && tokyocabinet_class.include?(":big")
|
16
|
+
big = true
|
17
|
+
tokyocabinet_class = tokyocabinet_class.split(":").first
|
18
|
+
else
|
19
|
+
big = false
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
database = Log.ignore_stderr do Persist::CONNECTIONS[path] ||= tokyocabinet_class.new end
|
22
|
+
dir = File.dirname(File.expand_path(path))
|
23
|
+
Open.mkdir(dir) unless File.exist?(dir)
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
tokyocabinet_class = tokyocabinet_class.to_s if Symbol === tokyocabinet_class
|
26
|
+
tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
|
27
|
+
tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
|
29
28
|
|
30
|
-
|
31
|
-
|
29
|
+
# Hack - Ignore warning: undefining the allocator of T_DATA class
|
30
|
+
# TokyoCabinet::HDB_data
|
31
|
+
database = Log.ignore_stderr do Persist::CONNECTIONS[path] ||= tokyocabinet_class.new end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
33
|
+
if big and not Open.exists?(path)
|
34
|
+
database.tune(nil, nil, nil, tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
database.persistence_class = tokyocabinet_class
|
37
|
+
flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
|
38
|
+
database.close
|
41
39
|
|
42
|
-
|
40
|
+
if !database.open(path, flags)
|
41
|
+
ecode = database.ecode
|
42
|
+
raise "Open error: #{database.errmsg(ecode)}. Trying to open file #{path}"
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
+
database.extend ScoutCabinet
|
46
|
+
database.persistence_path ||= path
|
47
|
+
database.persistence_class = tokyocabinet_class
|
45
48
|
|
46
|
-
|
49
|
+
database.open(path, tokyocabinet_class::OREADER)
|
47
50
|
|
48
|
-
|
49
|
-
end
|
51
|
+
database.define_singleton_method(:fingerprint){ "#{self.persistence_class}:#{self.persistence_path}" }
|
50
52
|
|
51
|
-
|
52
|
-
@closed = true
|
53
|
-
@writable = false
|
54
|
-
super
|
55
|
-
end
|
53
|
+
Persist::CONNECTIONS[path] = database
|
56
54
|
|
57
|
-
|
58
|
-
return if ! @writable && ! @closed && ! force
|
59
|
-
self.close
|
60
|
-
if !self.open(@persistence_path, persistence_class::OREADER)
|
61
|
-
ecode = self.ecode
|
62
|
-
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
55
|
+
database
|
63
56
|
end
|
64
57
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
58
|
+
def close
|
59
|
+
@closed = true
|
60
|
+
@writable = false
|
61
|
+
super
|
62
|
+
end
|
70
63
|
|
71
|
-
|
72
|
-
|
73
|
-
|
64
|
+
def read(force = false)
|
65
|
+
return if ! @writable && ! @closed && ! force
|
66
|
+
self.close
|
67
|
+
if !self.open(@persistence_path, persistence_class::OREADER)
|
68
|
+
ecode = self.ecode
|
69
|
+
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
70
|
+
end
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
72
|
+
@writable = false
|
73
|
+
@closed = false
|
78
74
|
|
75
|
+
self
|
76
|
+
end
|
79
77
|
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
def write?
|
79
|
+
@writable
|
80
|
+
end
|
83
81
|
|
84
|
-
|
85
|
-
|
86
|
-
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
82
|
+
def closed?
|
83
|
+
@closed
|
87
84
|
end
|
88
85
|
|
89
|
-
@writable = true
|
90
|
-
@closed = false
|
91
86
|
|
92
|
-
|
93
|
-
|
87
|
+
def write(force = true)
|
88
|
+
return if write? && ! closed? && ! force
|
89
|
+
self.close
|
94
90
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
91
|
+
if !self.open(@persistence_path, persistence_class::OWRITER)
|
92
|
+
ecode = self.ecode
|
93
|
+
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
94
|
+
end
|
95
|
+
|
96
|
+
@writable = true
|
97
|
+
@closed = false
|
98
|
+
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
def write_and_read
|
103
|
+
begin
|
104
|
+
write
|
105
|
+
yield
|
106
|
+
ensure
|
107
|
+
read
|
108
|
+
end
|
101
109
|
end
|
102
|
-
end
|
103
110
|
|
104
111
|
def write_and_close
|
105
112
|
begin
|
@@ -139,4 +146,5 @@ module ScoutCabinet
|
|
139
146
|
end
|
140
147
|
|
141
148
|
alias load_stream importtsv
|
149
|
+
end
|
142
150
|
end
|
@@ -23,6 +23,7 @@ module TSVAdapter
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def save_annotation_hash
|
26
|
+
self.close
|
26
27
|
self.with_write do
|
27
28
|
self.orig_set(ANNOTATION_ATTR_HASH_KEY, ANNOTATION_ATTR_HASH_SERIALIZER.dump(self.annotation_hash))
|
28
29
|
end
|
@@ -165,15 +166,6 @@ module TSVAdapter
|
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
168
|
-
def with_write(*args, &block)
|
169
|
-
if @write
|
170
|
-
yield
|
171
|
-
elsif @closed
|
172
|
-
write_and_close &block
|
173
|
-
else
|
174
|
-
write_and_read &block
|
175
|
-
end
|
176
|
-
end
|
177
169
|
|
178
170
|
def close(*args)
|
179
171
|
begin
|
@@ -250,12 +242,11 @@ module TSVAdapter
|
|
250
242
|
|
251
243
|
lock do
|
252
244
|
write(true) if closed? || ! write?
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
res
|
245
|
+
begin
|
246
|
+
yield
|
247
|
+
ensure
|
248
|
+
close
|
249
|
+
end
|
259
250
|
end
|
260
251
|
end
|
261
252
|
|
@@ -272,18 +263,13 @@ module TSVAdapter
|
|
272
263
|
return yield
|
273
264
|
else
|
274
265
|
if self.read?
|
275
|
-
self.write_and_read
|
276
|
-
return yield
|
277
|
-
end
|
266
|
+
self.write_and_read(&block)
|
278
267
|
else
|
279
|
-
self.write_and_close
|
280
|
-
return yield
|
281
|
-
end
|
268
|
+
self.write_and_close(&block)
|
282
269
|
end
|
283
270
|
end
|
284
271
|
end
|
285
272
|
|
286
|
-
|
287
273
|
def read_and_close
|
288
274
|
if read? || write?
|
289
275
|
begin
|
data/lib/scout/tsv/annotation.rb
CHANGED
@@ -48,12 +48,12 @@ module Annotation
|
|
48
48
|
|
49
49
|
fields = fields.flatten.compact.uniq
|
50
50
|
|
51
|
-
annotations = if Annotation.is_annotated?(objs)
|
52
|
-
objs.
|
51
|
+
annotations = if Annotation.is_annotated?(objs)
|
52
|
+
objs.annotation_hash.keys
|
53
53
|
elsif (Array === objs && objs.any?)
|
54
54
|
first = objs.compact.first
|
55
55
|
if Annotation.is_annotated?(first)
|
56
|
-
objs.compact.first.
|
56
|
+
objs.compact.first.annotation_hash.keys
|
57
57
|
else
|
58
58
|
raise "Objects didn't have annotations"
|
59
59
|
end
|
@@ -158,7 +158,7 @@ module Annotation
|
|
158
158
|
Annotation.load_tsv_values(id, values, tsv.fields)
|
159
159
|
end
|
160
160
|
|
161
|
-
case tsv.key_field
|
161
|
+
case tsv.key_field
|
162
162
|
when "List"
|
163
163
|
annotated_objects.first
|
164
164
|
else
|
data/lib/scout/tsv/index.rb
CHANGED
@@ -66,8 +66,6 @@ module TSV
|
|
66
66
|
index = TSV.setup({}, :type => :single)
|
67
67
|
end
|
68
68
|
|
69
|
-
tsv_file = TSV.open(tsv_file, **data_options) if ! TSV === tsv_file
|
70
|
-
|
71
69
|
log_msg = "Index #{Log.fingerprint tsv_file} target #{Log.fingerprint target}"
|
72
70
|
Log.low log_msg
|
73
71
|
bar = log_msg if TrueClass === bar
|
data/lib/scout/tsv/parser.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
require 'scout/named_array'
|
2
2
|
module TSV
|
3
|
+
def self.acceptable_parser_options(func = nil)
|
4
|
+
if func.nil?
|
5
|
+
TSV.method(:parse_line).parameters.collect{|a| a.last } +
|
6
|
+
TSV.method(:parse_stream).parameters.collect{|a| a.last } +
|
7
|
+
TSV.method(:parse).parameters.collect{|a| a.last } - [:line, :block]
|
8
|
+
else
|
9
|
+
TSV.method(func).parameters.collect{|a| a.last }
|
10
|
+
end.uniq
|
11
|
+
end
|
12
|
+
|
3
13
|
def self.cast_value(value, cast)
|
4
14
|
if Array === value
|
5
15
|
value.collect{|e| cast_value(e, cast) }
|
@@ -7,7 +17,7 @@ module TSV
|
|
7
17
|
if Proc === cast
|
8
18
|
cast.call value
|
9
19
|
else
|
10
|
-
if value.nil? || value
|
20
|
+
if value.nil? || value == ""
|
11
21
|
nil
|
12
22
|
else
|
13
23
|
value.send(cast)
|
data/lib/scout/tsv/stream.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module TSV
|
2
|
-
def self.paste_streams(streams, type: nil, sort: nil, sort_memory: nil, sep: nil, preamble: nil, header: nil, same_fields: nil, fix_flat: nil, all_match: nil, one2one: true, field_prefix: nil)
|
2
|
+
def self.paste_streams(streams, type: nil, sort: nil, sort_cmd_args: nil, sort_memory: nil, sep: nil, preamble: nil, header: nil, same_fields: nil, fix_flat: nil, all_match: nil, one2one: true, field_prefix: nil)
|
3
3
|
sep = "\t" if sep.nil?
|
4
4
|
|
5
5
|
streams = streams.collect do |stream|
|
@@ -20,7 +20,7 @@ module TSV
|
|
20
20
|
num_streams = streams.length
|
21
21
|
|
22
22
|
streams = streams.collect do |stream|
|
23
|
-
Open.sort_stream(stream, memory: sort_memory)
|
23
|
+
Open.sort_stream(stream, memory: sort_memory, cmd_args: sort_cmd_args)
|
24
24
|
end if sort
|
25
25
|
|
26
26
|
begin
|
@@ -193,7 +193,7 @@ module TSV
|
|
193
193
|
dumper.close
|
194
194
|
|
195
195
|
streams.each do |stream|
|
196
|
-
stream.close if stream.respond_to?(:close)
|
196
|
+
stream.close if stream.respond_to?(:close)
|
197
197
|
stream.join if stream.respond_to?(:join)
|
198
198
|
end
|
199
199
|
end
|
@@ -175,5 +175,17 @@ module TSV
|
|
175
175
|
end
|
176
176
|
res
|
177
177
|
end
|
178
|
+
|
179
|
+
def head(max=10)
|
180
|
+
res = self.annotate({})
|
181
|
+
transformer = Transformer.new self, res
|
182
|
+
i = 0
|
183
|
+
transformer.traverse do |k,v|
|
184
|
+
i += 1
|
185
|
+
break if i > max
|
186
|
+
[k, v]
|
187
|
+
end
|
188
|
+
res
|
189
|
+
end
|
178
190
|
end
|
179
191
|
|
@@ -30,9 +30,9 @@ module TSV
|
|
30
30
|
when type == :flat
|
31
31
|
self[key] = new_values
|
32
32
|
else
|
33
|
-
if ! values[field_pos].frozen? && ((String === values[field_pos] && String === new_values) ||
|
33
|
+
if ! values[field_pos].frozen? && ! NamedArray === values && ((String === values[field_pos] && String === new_values) ||
|
34
34
|
(Array === values[field_pos] && Array === new_values))
|
35
|
-
|
35
|
+
values[field_pos].replace new_values
|
36
36
|
else
|
37
37
|
values[field_pos] = new_values
|
38
38
|
end
|
data/lib/scout/tsv.rb
CHANGED
@@ -13,8 +13,12 @@ module Workflow
|
|
13
13
|
|
14
14
|
end
|
15
15
|
|
16
|
+
def to_s
|
17
|
+
@name || super
|
18
|
+
end
|
19
|
+
|
16
20
|
def name
|
17
|
-
@name
|
21
|
+
@name || to_s
|
18
22
|
end
|
19
23
|
|
20
24
|
def helpers
|
@@ -192,7 +196,7 @@ module Workflow
|
|
192
196
|
when 'true'
|
193
197
|
dep.clean
|
194
198
|
when 'recursive'
|
195
|
-
(dep.dependencies + dep.rec_dependencies).uniq.each do |d|
|
199
|
+
(dep.dependencies.to_a + dep.rec_dependencies.to_a).uniq.each do |d|
|
196
200
|
next if d.overriden
|
197
201
|
d.clean unless Scout::Config.get(:remove_dep, "task:#{d.task_signature}", "task:#{d.task_name}", "workflow:#{d.workflow.name}", :default => true).to_s == 'false'
|
198
202
|
end
|
@@ -164,7 +164,7 @@ module Workflow
|
|
164
164
|
def self.trace(seed_jobs, options = {})
|
165
165
|
jobs = []
|
166
166
|
seed_jobs.each do |step|
|
167
|
-
jobs += step.rec_dependencies + [step]
|
167
|
+
jobs += step.rec_dependencies.to_a + [step]
|
168
168
|
step.info[:archived_info].each do |path,ainfo|
|
169
169
|
next unless Hash === ainfo
|
170
170
|
archived_step = Step.new path
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Step
|
2
|
-
def rec_dependencies(connected = false, seen =
|
2
|
+
def rec_dependencies(connected = false, seen = Set.new)
|
3
3
|
@rec_dependencies = {}
|
4
4
|
@rec_dependencies[connected] ||= begin
|
5
5
|
direct_deps = []
|
@@ -8,11 +8,8 @@ class Step
|
|
8
8
|
next if connected && dep.done? && dep.updated?
|
9
9
|
direct_deps << dep
|
10
10
|
end if dependencies
|
11
|
-
seen
|
12
|
-
seen
|
13
|
-
direct_deps.inject(direct_deps){|acc,d| acc.concat(d.rec_dependencies(connected, seen)); acc }
|
14
|
-
direct_deps.uniq!
|
15
|
-
direct_deps
|
11
|
+
seen += direct_deps.collect{|d| d.path }
|
12
|
+
direct_deps.inject(Set.new(direct_deps)){|acc,d| acc += d.rec_dependencies(connected, seen) }
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
@@ -1,5 +1,6 @@
|
|
1
|
+
require 'scout/config'
|
1
2
|
class Step
|
2
|
-
SERIALIZER = :
|
3
|
+
SERIALIZER = Scout::Config.get(:serializer, :step_info, :info, :step, env: "SCOUT_SERIALIZER", default: :json)
|
3
4
|
def info_file
|
4
5
|
return nil if @path.nil?
|
5
6
|
@info_file ||= begin
|
@@ -13,7 +14,11 @@ class Step
|
|
13
14
|
info = begin
|
14
15
|
Persist.load(info_file, SERIALIZER) || {}
|
15
16
|
rescue
|
16
|
-
|
17
|
+
begin
|
18
|
+
Persist.load(info_file, :marshal) || {}
|
19
|
+
rescue
|
20
|
+
{status: :noinfo}
|
21
|
+
end
|
17
22
|
end
|
18
23
|
IndiferentHash.setup(info)
|
19
24
|
end
|
@@ -50,6 +55,15 @@ class Step
|
|
50
55
|
@info
|
51
56
|
end
|
52
57
|
|
58
|
+
def pid
|
59
|
+
info[:pid]
|
60
|
+
end
|
61
|
+
|
62
|
+
def pid=(pid)
|
63
|
+
set_info :pid, pid
|
64
|
+
end
|
65
|
+
|
66
|
+
|
53
67
|
def merge_info(new_info)
|
54
68
|
info = self.info
|
55
69
|
new_info.each do |key,value|
|
@@ -121,7 +135,7 @@ class Step
|
|
121
135
|
if message.nil?
|
122
136
|
Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), Log.color(:path, path)] * " "
|
123
137
|
else
|
124
|
-
message = Log.fingerprint(message).sub(/^'/,'').sub(/'$/,'')
|
138
|
+
message = Log.fingerprint(message.split("\n").first).sub(/^'/,'').sub(/'$/,'')
|
125
139
|
Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), message, Log.color(:path, path)] * " "
|
126
140
|
end
|
127
141
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative 'inputs'
|
2
|
+
module Workflow
|
3
|
+
|
4
|
+
def rec_inputs(task_name)
|
5
|
+
tasks[task_name].recursive_inputs.collect{|name, _| name }
|
6
|
+
end
|
7
|
+
|
8
|
+
def rec_input_types(task_name)
|
9
|
+
tasks[task_name].recursive_inputs.inject({}) do |acc,l|
|
10
|
+
name, type, desc, default, options = l
|
11
|
+
acc.merge!(name => type) unless acc.include?(name)
|
12
|
+
acc
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def rec_input_descriptions(task_name)
|
18
|
+
tasks[task_name].recursive_inputs.inject({}) do |acc,l|
|
19
|
+
name, type, desc, default, options = l
|
20
|
+
acc.merge!(name => desc) unless desc.nil? || acc.include?(name)
|
21
|
+
acc
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def rec_input_defaults(task_name)
|
26
|
+
tasks[task_name].recursive_inputs.inject({}) do |acc,l|
|
27
|
+
name, type, desc, default, options = l
|
28
|
+
acc.merge!(name => default) unless default.nil? || acc.include?(name)
|
29
|
+
acc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def rec_input_options(task_name)
|
34
|
+
tasks[task_name].recursive_inputs.inject({}) do |acc,l|
|
35
|
+
name, type, desc, default, options = l
|
36
|
+
acc.merge!(name => options) unless options.nil? unless acc.include?(name)
|
37
|
+
acc
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def rec_input_use(task_name)
|
43
|
+
input_use = {}
|
44
|
+
task = self.tasks[task_name]
|
45
|
+
task.inputs.each do |name,_|
|
46
|
+
input_use[name] ||= {}
|
47
|
+
input_use[name][self] ||= []
|
48
|
+
input_use[name][self] << task_name
|
49
|
+
end
|
50
|
+
|
51
|
+
task.deps.inject(input_use) do |acc,p|
|
52
|
+
workflow, task_name = p
|
53
|
+
next if task_name.nil?
|
54
|
+
workflow.rec_input_use(task_name).each do |name,uses|
|
55
|
+
acc[name] ||= {}
|
56
|
+
uses.each do |workflow, task_names|
|
57
|
+
acc[name][workflow] ||= []
|
58
|
+
acc[name][workflow].concat(task_names)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
acc
|
62
|
+
end if task.deps
|
63
|
+
|
64
|
+
input_use
|
65
|
+
end
|
66
|
+
def task_info(name)
|
67
|
+
name = name.to_sym
|
68
|
+
task = tasks[name]
|
69
|
+
raise "No '#{name}' task in '#{self.name}' Workflow" if task.nil?
|
70
|
+
id = File.join(self.name, name.to_s)
|
71
|
+
@task_info ||= {}
|
72
|
+
@task_info[id] ||= begin
|
73
|
+
description = task.description
|
74
|
+
returns = task.returns
|
75
|
+
|
76
|
+
inputs = rec_inputs(name).uniq
|
77
|
+
input_types = rec_input_types(name)
|
78
|
+
input_descriptions = rec_input_descriptions(name)
|
79
|
+
input_use = rec_input_use(name)
|
80
|
+
input_defaults = rec_input_defaults(name)
|
81
|
+
input_options = rec_input_options(name)
|
82
|
+
extension = task.extension
|
83
|
+
|
84
|
+
dependencies = tasks[name].deps
|
85
|
+
{ :id => id,
|
86
|
+
:description => description,
|
87
|
+
:inputs => inputs,
|
88
|
+
:input_types => input_types,
|
89
|
+
:input_descriptions => input_descriptions,
|
90
|
+
:input_defaults => input_defaults,
|
91
|
+
:input_options => input_options,
|
92
|
+
:input_use => input_use,
|
93
|
+
:returns => returns,
|
94
|
+
:dependencies => dependencies,
|
95
|
+
:extension => extension
|
96
|
+
}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|