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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +47 -32
  3. data/VERSION +1 -1
  4. data/bin/scout +15 -2
  5. data/lib/scout/association/index.rb +4 -0
  6. data/lib/scout/association/item.rb +1 -1
  7. data/lib/scout/association.rb +32 -10
  8. data/lib/scout/entity/identifiers.rb +2 -2
  9. data/lib/scout/entity/property.rb +2 -2
  10. data/lib/scout/knowledge_base/enrichment.rb +9 -0
  11. data/lib/scout/knowledge_base/entity.rb +152 -0
  12. data/lib/scout/knowledge_base/list.rb +95 -0
  13. data/lib/scout/knowledge_base/query.rb +96 -0
  14. data/lib/scout/knowledge_base/registry.rb +175 -0
  15. data/lib/scout/knowledge_base/traverse.rb +329 -0
  16. data/lib/scout/knowledge_base.rb +91 -0
  17. data/lib/scout/persist/engine/tokyocabinet.rb +85 -77
  18. data/lib/scout/persist/tsv/adapter/base.rb +8 -22
  19. data/lib/scout/tsv/annotation.rb +4 -4
  20. data/lib/scout/tsv/index.rb +0 -2
  21. data/lib/scout/tsv/parser.rb +11 -1
  22. data/lib/scout/tsv/stream.rb +3 -3
  23. data/lib/scout/tsv/transformer.rb +12 -0
  24. data/lib/scout/tsv/util/process.rb +2 -2
  25. data/lib/scout/tsv.rb +2 -0
  26. data/lib/scout/workflow/definition.rb +6 -2
  27. data/lib/scout/workflow/deployment/trace.rb +1 -1
  28. data/lib/scout/workflow/step/dependencies.rb +3 -6
  29. data/lib/scout/workflow/step/info.rb +17 -3
  30. data/lib/scout/workflow/task/info.rb +99 -0
  31. data/lib/scout/workflow/task.rb +1 -0
  32. data/scout-gear.gemspec +27 -7
  33. data/scout_commands/doc +3 -3
  34. data/scout_commands/kb/config +33 -0
  35. data/scout_commands/kb/entities +35 -0
  36. data/scout_commands/kb/list +39 -0
  37. data/scout_commands/{db → kb}/query +6 -11
  38. data/scout_commands/{db → kb}/register +9 -8
  39. data/scout_commands/{db → kb}/show +6 -16
  40. data/scout_commands/kb/traverse +66 -0
  41. data/scout_commands/workflow/task +7 -2
  42. data/test/data/person/brothers +1 -1
  43. data/test/scout/entity/test_identifiers.rb +3 -3
  44. data/test/scout/knowledge_base/test_enrichment.rb +0 -0
  45. data/test/scout/knowledge_base/test_entity.rb +38 -0
  46. data/test/scout/knowledge_base/test_list.rb +40 -0
  47. data/test/scout/knowledge_base/test_query.rb +39 -0
  48. data/test/scout/knowledge_base/test_registry.rb +35 -0
  49. data/test/scout/knowledge_base/test_traverse.rb +245 -0
  50. data/test/scout/persist/test_tsv.rb +1 -0
  51. data/test/scout/test_association.rb +32 -3
  52. data/test/scout/test_entity.rb +0 -15
  53. data/test/scout/test_knowledge_base.rb +27 -0
  54. data/test/scout/test_tsv.rb +15 -0
  55. data/test/scout/tsv/test_parser.rb +4 -0
  56. data/test/scout/tsv/test_transformer.rb +13 -0
  57. data/test/scout/workflow/step/test_info.rb +11 -0
  58. data/test/scout/workflow/task/test_info.rb +22 -0
  59. data/test/test_helper.rb +17 -0
  60. metadata +26 -9
@@ -1,105 +1,112 @@
1
- require 'tokyocabinet'
2
-
3
- module ScoutCabinet
4
- attr_accessor :persistence_path, :persistence_class
5
-
6
- def self.open(path, write = true, tokyocabinet_class = TokyoCabinet::HDB)
7
- path = path.find if Path === path
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
- dir = File.dirname(File.expand_path(path))
16
- Open.mkdir(dir) unless File.exist?(dir)
9
+ if continue
10
+ module ScoutCabinet
11
+ attr_accessor :persistence_path, :persistence_class
17
12
 
18
- tokyocabinet_class = tokyocabinet_class.to_s if Symbol === tokyocabinet_class
19
- tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
20
- tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
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
- # Hack - Ignore warning: undefining the allocator of T_DATA class
23
- # TokyoCabinet::HDB_data
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
- if big and not Open.exists?(path)
27
- database.tune(nil, nil, nil, tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
28
- end
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
- flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
31
- database.close
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
- if !database.open(path, flags)
34
- ecode = database.ecode
35
- raise "Open error: #{database.errmsg(ecode)}. Trying to open file #{path}"
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
- database.extend ScoutCabinet
39
- database.persistence_path ||= path
40
- database.persistence_class = tokyocabinet_class
37
+ flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
38
+ database.close
41
39
 
42
- database.open(path, tokyocabinet_class::OREADER)
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
- database.define_singleton_method(:fingerprint){ "#{self.persistence_class}:#{self.persistence_path}" }
45
+ database.extend ScoutCabinet
46
+ database.persistence_path ||= path
47
+ database.persistence_class = tokyocabinet_class
45
48
 
46
- Persist::CONNECTIONS[path] = database
49
+ database.open(path, tokyocabinet_class::OREADER)
47
50
 
48
- database
49
- end
51
+ database.define_singleton_method(:fingerprint){ "#{self.persistence_class}:#{self.persistence_path}" }
50
52
 
51
- def close
52
- @closed = true
53
- @writable = false
54
- super
55
- end
53
+ Persist::CONNECTIONS[path] = database
56
54
 
57
- def read(force = false)
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
- @writable = false
66
- @closed = false
67
-
68
- self
69
- end
58
+ def close
59
+ @closed = true
60
+ @writable = false
61
+ super
62
+ end
70
63
 
71
- def write?
72
- @writable
73
- end
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
- def closed?
76
- @closed
77
- end
72
+ @writable = false
73
+ @closed = false
78
74
 
75
+ self
76
+ end
79
77
 
80
- def write(force = true)
81
- return if write? && ! closed? && ! force
82
- self.close
78
+ def write?
79
+ @writable
80
+ end
83
81
 
84
- if !self.open(@persistence_path, persistence_class::OWRITER)
85
- ecode = self.ecode
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
- self
93
- end
87
+ def write(force = true)
88
+ return if write? && ! closed? && ! force
89
+ self.close
94
90
 
95
- def write_and_read
96
- begin
97
- write
98
- yield
99
- ensure
100
- read
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
- res = begin
254
- yield
255
- ensure
256
- close
257
- end
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 do
276
- return yield
277
- end
266
+ self.write_and_read(&block)
278
267
  else
279
- self.write_and_close do
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
@@ -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.annotations
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.annotations
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
@@ -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
@@ -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.empty?
20
+ if value.nil? || value == ""
11
21
  nil
12
22
  else
13
23
  value.send(cast)
@@ -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) && ! stream.closed?
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
- values[field_pos].replace new_values
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
@@ -133,6 +133,8 @@ module TSV
133
133
 
134
134
  tsv.unnamed = unnamed unless unnamed.nil?
135
135
 
136
+ tsv.entity_options = entity_options
137
+
136
138
  tsv
137
139
  end
138
140
  end
@@ -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 ||= self.to_s
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.concat direct_deps.collect{|d| d.path }
12
- seen.uniq!
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 = :marshal
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
- {status: :noinfo}
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
@@ -3,6 +3,7 @@ require 'scout/named_array'
3
3
  require_relative 'step'
4
4
  require_relative 'task/inputs'
5
5
  require_relative 'task/dependencies'
6
+ require_relative 'task/info'
6
7
 
7
8
  module Task
8
9
  extend Annotation