scout-gear 10.0.1 → 10.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5af158e978a724dacd722c9584cb4fd3b7f46fff8a4619272b1d2c2258418600
4
- data.tar.gz: 6bd5da8eba38542376f4b5566154fc16105f3742ba0758a37139d0ff9679d06e
3
+ metadata.gz: 3e807e8eea8b8ff3b40be002fcd9cdfa9fbc8d3fdb447f20b1b3c56f1c318de8
4
+ data.tar.gz: 8838111c9867b63671060c82b7224f2ac310b64d375f0cc62c26b42092da6f1d
5
5
  SHA512:
6
- metadata.gz: e9f6f4d2a5e223d740332b627c9606907d69536696f477401087b4f72bee09d1b374d060275ecb3fad5e38c27010417d36d661d985c58d71e3cec4bf04bbcbf7
7
- data.tar.gz: a7b8e5d1bfd1057bd93cfbd4a2439bccf0e28848f3e08923c81da8bcc2fe1a489ffb2e220587ecb4533ad0cf7edcf506f3c4557955dfa11356d816b87b379968
6
+ metadata.gz: 2dcc68c9d612b208d6b6b94dd366ef37f2467b364d1da8367b1f6833d305d6ef8c35a1dc0f0e27c6e00ce481344e230e20ac6eb85236dd27c75c59e8ad3f0ec5
7
+ data.tar.gz: 85d8e7458a1453966e2e123fc8ced3a0c2bc8be884a7570f1bb57f4d260db582e90380d2ea0f8a91c91b68decb8439e8b556d294b9d71258c522fa06628ec22b
data/.vimproject CHANGED
@@ -8,6 +8,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
8
8
  alias
9
9
  find
10
10
  glob
11
+ log
11
12
  doc
12
13
  update
13
14
  template
@@ -16,7 +17,14 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
16
17
  task
17
18
  list
18
19
  info
20
+ write_info
19
21
  install
22
+ trace
23
+ prov
24
+ }
25
+ batch=batch{
26
+ list
27
+ clean
20
28
  }
21
29
  resource=resource{
22
30
  produce
@@ -28,81 +36,6 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
28
36
  rbbt-scout.rb
29
37
  scout.rb
30
38
  scout=scout{
31
- meta_extension.rb
32
- exceptions.rb
33
-
34
- misc.rb
35
- misc=misc{
36
- format.rb
37
- insist.rb
38
- digest.rb
39
- filesystem.rb
40
- monitor.rb
41
- system.rb
42
- }
43
- named_array.rb
44
- indiferent_hash.rb
45
- indiferent_hash=indiferent_hash{
46
- case_insensitive.rb
47
- options.rb
48
- }
49
- log.rb
50
- log=log{
51
- color.rb
52
- color_class.rb
53
- fingerprint.rb
54
- progress.rb
55
- progress=progress{
56
- report.rb
57
- util.rb
58
- }
59
- trap.rb
60
- }
61
- tmpfile.rb
62
- simple_opt.rb
63
- simple_opt=simple_opt{
64
- accessor.rb
65
- doc.rb
66
- parse.rb
67
- get.rb
68
- setup.rb
69
- }
70
- path.rb
71
- path=path{
72
- find.rb
73
- util.rb
74
- tmpfile.rb
75
- }
76
- concurrent_stream.rb
77
- cmd.rb
78
- open.rb
79
- open=open{
80
- lock.rb
81
- remote.rb
82
- stream.rb
83
- util.rb
84
- lock=lock{
85
- lockfile.rb
86
- }
87
- }
88
- resource.rb
89
- resource=resource{
90
- produce.rb
91
- produce=produce{
92
- rake.rb
93
- }
94
- software.rb
95
- scout.rb
96
- util.rb
97
- path.rb
98
- }
99
- config.rb
100
- persist.rb
101
- persist=persist{
102
- serialize.rb
103
- open.rb
104
- path.rb
105
- }
106
39
  workflow.rb
107
40
  workflow=workflow{
108
41
  definition.rb
@@ -146,6 +79,8 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
146
79
  process.rb
147
80
  unzip.rb
148
81
  reorder.rb
82
+ sort.rb
83
+ melt.rb
149
84
  }
150
85
  parser.rb
151
86
  dumper.rb
@@ -173,9 +108,6 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
173
108
  sync.rb
174
109
  step.rb
175
110
  }
176
- hpc=hpc{
177
- slurm.rb
178
- }
179
111
  }
180
112
  }
181
113
  test=test {
@@ -199,6 +131,10 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
199
131
  test_tsv.rb
200
132
  test_work_queue.rb
201
133
  test_workflow.rb
134
+ work_queue=work_queue{
135
+ test_socket.rb
136
+ test_worker.rb
137
+ }
202
138
  workflow=workflow{
203
139
  test_definition.rb
204
140
  test_documentation.rb
@@ -217,10 +153,42 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
217
153
  test_dependencies.rb
218
154
  test_inputs.rb
219
155
  }
156
+ deployment=deployment{
157
+ test_orchestrator.rb
158
+ }
159
+ }
160
+ tsv=tsv{
161
+ test_attach.rb
162
+ test_change_id.rb
163
+ test_dumper.rb
164
+ test_index.rb
165
+ test_open.rb
166
+ test_parser.rb
167
+ test_persist.rb
168
+ test_stream.rb
169
+ test_transformer.rb
170
+ test_traverse.rb
171
+ test_util.rb
172
+ util=util{
173
+ test_filter.rb
174
+ test_melt.rb
175
+ test_process.rb
176
+ test_reorder.rb
177
+ test_select.rb
178
+ test_sort.rb
179
+ test_unzip.rb
180
+ }
181
+ persist=persist{
182
+ test_adapter.rb
183
+ test_fix_width_table.rb
184
+ test_tokyocabinet.rb
185
+ }
220
186
  }
221
- indiferent_hash=indiferent_hash{
222
- test_case_insensitive.rb
223
- test_options.rb
187
+ offsite=offsite{
188
+ test_ssh.rb
189
+ test_step.rb
190
+ test_sync.rb
191
+ test_task.rb
224
192
  }
225
193
  }
226
194
  }
@@ -601,6 +569,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
601
569
  test_filter.rb
602
570
  test_index.rb
603
571
  test_manipulate.rb
572
+ test_marshal.rb
604
573
  test_matrix.rb
605
574
  test_parallel.rb
606
575
  test_parser.rb
data/Rakefile CHANGED
@@ -35,6 +35,7 @@ Juwelier::RubygemsDotOrgTasks.new
35
35
 
36
36
  require 'rake/testtask'
37
37
  Rake::TestTask.new(:test) do |test|
38
+ ENV["SCOUT_LOG"] = "NONE"
38
39
  test.libs << 'lib' << 'test'
39
40
  test.pattern = 'test/**/test_*.rb'
40
41
  test.verbose = true
data/VERSION CHANGED
@@ -1 +1 @@
1
- 10.0.1
1
+ 10.2.0
@@ -2,15 +2,16 @@ module TSV
2
2
  class Transformer
3
3
  attr_accessor :unnamed, :parser, :dumper
4
4
 
5
- def initialize(parser, dumper = nil, unnamed: false)
5
+ def initialize(parser, dumper = nil, unnamed: nil)
6
6
  if TSV::Parser === parser
7
7
  @parser = parser
8
8
  elsif TSV === parser
9
9
  @parser = parser
10
+ @unnamed = parser.unnamed
10
11
  else
11
12
  @parser = TSV::Parser.new parser
12
13
  end
13
- @unnamed = unnamed
14
+ @unnamed = unnamed unless unnamed.nil?
14
15
  if dumper.nil?
15
16
  @dumper = TSV::Dumper.new(@parser)
16
17
  @dumper.sep = "\t"
@@ -70,7 +71,7 @@ module TSV
70
71
  @dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
71
72
  Log.debug "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @dumper}"
72
73
  Open.traverse(@parser, *args, **kwargs) do |k,v|
73
- NamedArray.setup(v, @parser.fields, k) unless @unnamed
74
+ NamedArray.setup(v, @parser.fields, k) unless @unnamed || @parser.fields.nil?
74
75
  block.call k, v
75
76
  end
76
77
  end
@@ -112,16 +113,18 @@ module TSV
112
113
 
113
114
  def to_list
114
115
  res = self.annotate({})
115
- transformer = Transformer.new self, res
116
- transformer.type = :list
117
- transformer.traverse do |k,v|
118
- case self.type
119
- when :single
120
- [k, [v]]
121
- when :double
122
- [k, v.collect{|v| v.first }]
123
- when :flat
124
- [k, v.slice(0,1)]
116
+ self.with_unnamed do
117
+ transformer = Transformer.new self, res
118
+ transformer.type = :list
119
+ transformer.traverse do |k,v|
120
+ case self.type
121
+ when :single
122
+ [k, [v]]
123
+ when :double
124
+ [k, v.collect{|v| v.first }]
125
+ when :flat
126
+ [k, v.slice(0,1)]
127
+ end
125
128
  end
126
129
  end
127
130
  res
@@ -131,6 +134,7 @@ module TSV
131
134
  res = self.annotate({})
132
135
  transformer = Transformer.new self, res
133
136
  transformer.type = :single
137
+ transformer.unnamed = true
134
138
  transformer.traverse do |k,v|
135
139
  v = v.first while Array === v
136
140
  [k, v]
@@ -0,0 +1,13 @@
1
+ module TSV
2
+ def melt_columns(value_field, column_field)
3
+ target = TSV.setup({}, :key_field => "ID", :fields => [key_field, value_field, column_field], :type => :list, :cast => cast)
4
+ each do |k,values|
5
+ i = 0
6
+ values.zip(fields).each do |v,f|
7
+ target["#{k}:#{i}"] = [k,v,f]
8
+ i+=1
9
+ end
10
+ end
11
+ target
12
+ end
13
+ end
@@ -0,0 +1,74 @@
1
+ module TSV
2
+ def sort_by(field = nil, just_keys = false, &block)
3
+ field = :all if field.nil?
4
+
5
+ if field == :all
6
+ elems = collect
7
+ else
8
+ elems = []
9
+ case type
10
+ when :single
11
+ through :key, field do |key, field|
12
+ elems << [key, field]
13
+ end
14
+ when :list, :flat
15
+ through :key, field do |key, fields|
16
+ elems << [key, fields.first]
17
+ end
18
+ when :double
19
+ through :key, field do |key, fields|
20
+ elems << [key, fields.first]
21
+ end
22
+ end
23
+ end
24
+
25
+ if not block_given?
26
+ if fields == :all
27
+ if just_keys
28
+ keys = elems.sort_by{|key, value| key }.collect{|key, values| key}
29
+ keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
30
+ else
31
+ elems.sort_by{|key, value| key }
32
+ end
33
+ else
34
+ sorted = elems.sort do |a, b|
35
+ a_value = a.last
36
+ b_value = b.last
37
+ a_empty = a_value.nil? or (a_value.respond_to?(:empty?) and a_value.empty?)
38
+ b_empty = b_value.nil? or (b_value.respond_to?(:empty?) and b_value.empty?)
39
+ case
40
+ when (a_empty and b_empty)
41
+ 0
42
+ when a_empty
43
+ -1
44
+ when b_empty
45
+ 1
46
+ when Array === a_value
47
+ if a_value.length == 1 and b_value.length == 1
48
+ a_value.first <=> b_value.first
49
+ else
50
+ a_value.length <=> b_value.length
51
+ end
52
+ else
53
+ a_value <=> b_value
54
+ end
55
+ end
56
+ if just_keys
57
+ keys = sorted.collect{|key, value| key}
58
+ keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true)) unless @unnamed
59
+ keys
60
+ else
61
+ sorted.collect{|key, value| [key, self[key]]}
62
+ end
63
+ end
64
+ else
65
+ if just_keys
66
+ keys = elems.sort_by(&block).collect{|key, value| key}
67
+ keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true)) unless @unnamed
68
+ keys
69
+ else
70
+ elems.sort_by(&block).collect{|key, value| [key, self[key]]}
71
+ end
72
+ end
73
+ end
74
+ end
@@ -6,6 +6,8 @@ require_relative 'util/process'
6
6
  require_relative 'util/select'
7
7
  require_relative 'util/reorder'
8
8
  require_relative 'util/unzip'
9
+ require_relative 'util/sort'
10
+ require_relative 'util/melt'
9
11
  module TSV
10
12
  def self.identify_field(key_field, fields, name, strict: nil)
11
13
  return :key if name == :key || (! strict && NamedArray.field_match(key_field, name))
data/lib/scout/tsv.rb CHANGED
@@ -34,11 +34,14 @@ module TSV
34
34
  end
35
35
 
36
36
  def self.open(file, options = {})
37
- persist, type, grep, invert_grep = IndiferentHash.process_options options, :persist, :persist_type, :grep, :invert_grep, :persist => false, :persist_type => "HDB"
38
- type = type.to_sym if type
37
+ grep, invert_grep = IndiferentHash.process_options options, :grep, :invert_grep, :persist => false
38
+
39
+ persist_options = IndiferentHash.pull_keys options, :persist
40
+ persist_options = IndiferentHash.add_defaults persist_options, :prefix => "TSV", :type => "HDB"
41
+
39
42
  file = StringIO.new file if String === file && ! (Path === file) && file.index("\n")
40
- Persist.persist(file, type, options.merge(:persist => persist, :prefix => "Tsv", :other_options => options)) do |filename|
41
- data = filename ? ScoutCabinet.open(filename, true, type) : nil
43
+ Persist.persist(file, persist_options[:type], persist_options.merge(:other_options => options)) do |filename|
44
+ data = filename ? ScoutCabinet.open(filename, true, persist_options[:type]) : nil
42
45
  options[:data] = data if data
43
46
  options[:filename] = file
44
47
 
@@ -84,8 +84,10 @@ module Workflow
84
84
  annotate_next_task :deps, [workflow, task, options, block, args]
85
85
  end
86
86
 
87
- def input(*args)
88
- annotate_next_task(:inputs, args)
87
+ def input(name, type = nil, *rest)
88
+ name = name.to_sym
89
+ type = type.to_sym if type
90
+ annotate_next_task(:inputs, [name, type] + rest)
89
91
  end
90
92
 
91
93
  def desc(description)
@@ -102,6 +104,8 @@ module Workflow
102
104
 
103
105
  def task(name_and_type, &block)
104
106
  name, type = name_and_type.collect.first
107
+ type = type.to_sym if String === type
108
+ name = name.to_sym if String === name
105
109
  @tasks ||= IndiferentHash.setup({})
106
110
  block = self.method(name) if block.nil?
107
111
  begin
@@ -132,8 +136,10 @@ module Workflow
132
136
  def task_alias(name, workflow, oname, *rest, &block)
133
137
  dep(workflow, oname, *rest, &block)
134
138
  extension :dep_task unless @extension
135
- returns workflow.tasks[oname].returns if @returns.nil?
136
- type = workflow.tasks[oname].type
139
+ task_proc = workflow.tasks[oname]
140
+ raise "Task #{name} not found" if task_proc.nil?
141
+ returns task_proc.returns if @returns.nil?
142
+ type = task_proc.type
137
143
  task name => type do
138
144
  raise RbbtException, "dep_task does not have any dependencies" if dependencies.empty?
139
145
  Step.wait_for_jobs dependencies.select{|d| d.streaming? }
@@ -5,7 +5,7 @@ class Step
5
5
  next if seen.include? dep.path
6
6
  next if connected && dep.done? && dep.updated?
7
7
  direct_deps << dep
8
- end
8
+ end if dependencies
9
9
  seen.concat direct_deps.collect{|d| d.path }
10
10
  direct_deps.inject(direct_deps){|acc,d| acc.concat(d.rec_dependencies(connected, seen)); acc }
11
11
  end
@@ -12,9 +12,10 @@ class Step
12
12
  end
13
13
  end
14
14
 
15
- def file(file)
15
+ def file(file = nil)
16
16
  dir = files_dir
17
17
  Path.setup(dir) unless Path === dir
18
+ return dir if file.nil?
18
19
  dir[file]
19
20
  end
20
21
 
@@ -68,7 +68,7 @@ class Step
68
68
  $inputs.each do |input|
69
69
  value = job_inputs[input]
70
70
  next if value.nil?
71
- value_str = Misc.fingerprint(value)
71
+ value_str = Log.fingerprint(value)
72
72
  str << "\t#{Log.color :magenta, input}=#{value_str}"
73
73
  end
74
74
  end
@@ -78,7 +78,7 @@ class Step
78
78
  IndiferentHash.setup(info)
79
79
  value = info[field]
80
80
  next if value.nil?
81
- value_str = Misc.fingerprint(value)
81
+ value_str = Log.fingerprint(value)
82
82
  str << "\t#{Log.color :magenta, field}=#{value_str}"
83
83
  end
84
84
  end
@@ -27,10 +27,11 @@ class Step
27
27
  @result = nil
28
28
  @info = nil
29
29
  @info_load_time = nil
30
- Open.rm path if Open.exist?(path)
31
- Open.rm tmp_path if Open.exist?(tmp_path)
32
- Open.rm info_file if Open.exist?(info_file)
33
- Open.rm_rf files_dir if Open.exist?(files_dir)
30
+ Open.rm path if Open.exist_or_link?(path)
31
+ Open.rm tmp_path if Open.exist_or_link?(tmp_path)
32
+ Open.rm info_file if Open.exist_or_link?(info_file)
33
+ Open.rm_rf files_dir if Open.exist_or_link?(files_dir)
34
+ self
34
35
  end
35
36
 
36
37
  def self.clean(file)
@@ -76,10 +76,14 @@ class Step
76
76
 
77
77
  def task_name
78
78
  @task_name ||= @task.name if @task.respond_to?(:name)
79
+ @task_name ||= info[:task_name] if Open.exist?(info_file)
80
+ @task_name ||= path.split("/")[-2]
79
81
  end
80
82
 
81
83
  def workflow
82
- @task.workflow if @task
84
+ @workflow ||= @task.workflow if Task === @task
85
+ @workflow ||= info[:workflow] if Open.exist?(info_file)
86
+ @workflow ||= path.split("/")[-3]
83
87
  end
84
88
 
85
89
  def exec
@@ -124,62 +128,63 @@ class Step
124
128
  return @result || self.load if done?
125
129
  prepare_dependencies
126
130
  run_dependencies
127
- @result =
128
- begin
129
- Persist.persist(name, type, :path => path, :tee_copies => tee_copies) do
130
- clear_info
131
- input_names = (task.respond_to?(:inputs) && task.inputs) ? task.inputs.collect{|name,_| name} : []
132
- merge_info :status => :start, :start => Time.now,
133
- :pid => Process.pid, :pid_hostname => Misc.hostname,
134
- :inputs => MetaExtension.purge(inputs), :input_names => input_names, :type => type,
135
- :dependencies => dependencies.collect{|d| d.path }
136
-
137
- @result = exec
138
-
139
- if @result.nil? && File.exist?(self.tmp_path) && ! File.exist?(self.path)
140
- Open.mv self.tmp_path, self.path
141
- else
142
- @result = @result.stream if @result.respond_to?(:stream)
143
- end
131
+ begin
132
+ @result = Persist.persist(name, type, :path => path, :tee_copies => tee_copies) do
133
+ clear_info
134
+ input_names = (task.respond_to?(:inputs) && task.inputs) ? task.inputs.collect{|name,_| name} : []
135
+ merge_info :status => :start, :start => Time.now,
136
+ :pid => Process.pid, :pid_hostname => Misc.hostname,
137
+ :task_name => task_name, :workflow => workflow.to_s,
138
+ :inputs => MetaExtension.purge(inputs), :input_names => input_names, :type => type,
139
+ :dependencies => dependencies.collect{|d| d.path }
140
+
141
+ @exec_result = exec
142
+
143
+ if @exec_result.nil? && File.exist?(self.tmp_path) && ! File.exist?(self.path)
144
+ Open.mv self.tmp_path, self.path
145
+ else
146
+ @exec_result = @exec_result.stream if @exec_result.respond_to?(:stream)
147
+ end
144
148
 
145
- @result
149
+ @exec_result
146
150
 
147
- if (IO === @result || StringIO === @result) && (ENV["SCOUT_NO_STREAM"] == "true" || ! stream)
148
- Open.sensible_write(self.path, @result)
149
- @result = nil
150
- else
151
- @result
152
- end
151
+ if (IO === @exec_result || StringIO === @exec_result) && (ENV["SCOUT_NO_STREAM"] == "true" || ! stream)
152
+ Open.sensible_write(self.path, @exec_result)
153
+ @exec_result = nil
154
+ else
155
+ @exec_result
153
156
  end
154
- rescue Exception => e
155
- merge_info :status => :error, :exception => e, :end => Time.now
156
- abort_dependencies
157
- raise e
158
- ensure
159
- if ! (error? || aborted?)
160
- if streaming?
161
- ConcurrentStream.setup(@result) do
162
- merge_info :status => :done, :end => Time.now
163
- end
157
+ end
158
+ rescue Exception => e
159
+ merge_info :status => :error, :exception => e, :end => Time.now
160
+ abort_dependencies
161
+ raise e
162
+ ensure
163
+ if ! (error? || aborted?)
164
+ if streaming?
165
+ ConcurrentStream.setup(@result) do
166
+ merge_info :status => :done, :end => Time.now
167
+ end
164
168
 
165
- @result.abort_callback = proc do |exception|
166
- if exception.nil? || Aborted === exception || Interrupt === exception
167
- merge_info :status => :aborted, :end => Time.now
168
- else
169
- begin
170
- merge_info :status => :error, :exception => exception, :end => Time.now
171
- rescue Exception
172
- Log.exception $!
173
- end
169
+ @result.abort_callback = proc do |exception|
170
+ if exception.nil? || Aborted === exception || Interrupt === exception
171
+ merge_info :status => :aborted, :end => Time.now
172
+ else
173
+ begin
174
+ merge_info :status => :error, :exception => exception, :end => Time.now
175
+ rescue Exception
176
+ Log.exception $!
174
177
  end
175
178
  end
176
-
177
- log :streaming
178
- else
179
- merge_info :status => :done, :end => Time.now
180
179
  end
180
+
181
+
182
+ log :streaming
183
+ else
184
+ merge_info :status => :done, :end => Time.now
181
185
  end
182
186
  end
187
+ end
183
188
  end
184
189
 
185
190
  def fork
@@ -232,11 +237,14 @@ class Step
232
237
  while @result && streaming? && stream = self.stream
233
238
  threads << Open.consume_stream(stream, true)
234
239
  end
240
+
241
+ threads.compact!
242
+
235
243
  threads.each do |t|
236
244
  begin
237
245
  t.join
238
246
  rescue Exception
239
- threads.each{|t| t.raise(Aborted); t.join }
247
+ threads.compact.each{|t| t.raise(Aborted); t.join }
240
248
  raise $!
241
249
  end
242
250
  end
@@ -252,6 +260,7 @@ class Step
252
260
  while ! present?
253
261
  sleep 0.1
254
262
  end
263
+ self
255
264
  end
256
265
 
257
266
  def terminated?
@@ -85,8 +85,12 @@ module Task
85
85
  input_file = File.join(directory, name.to_s)
86
86
 
87
87
  if Path.is_filename?(value)
88
- relative_file = save_file_input(value, directory)
89
- Open.write(input_file + ".as_file", relative_file)
88
+ if type == :path
89
+ Open.write(input_file + ".as_path", value)
90
+ else
91
+ relative_file = save_file_input(value, directory)
92
+ Open.write(input_file + ".as_file", relative_file)
93
+ end
90
94
  elsif Step === value
91
95
  Open.write(input_file + ".as_step", value.short_path)
92
96
  elsif type == :file
@@ -52,8 +52,9 @@ module Task
52
52
  inputs = task.inputs.reject{|name, _| seen.include? name }
53
53
  inputs = task.inputs.reject{|name, _| options.include? name }
54
54
  next unless inputs.any?
55
- task.inputs.select{|name, _| inputs.include? name }.each do |name,_,_,_,options|
56
- selects << [i, options[:select_options]] if options[:select_options]
55
+ input_names = inputs.collect{|name,_| name }
56
+ task.inputs.select{|name,_| input_names.include? name }.each do |name,_,_,_,options|
57
+ selects << [name, options[:select_options]] if options && options[:select_options]
57
58
  end
58
59
 
59
60
  dep = workflow.nil? || dep_workflow.name != workflow.name ? ["#{dep_workflow.name}", task_name.to_s] *"#" : task_name.to_s
@@ -291,6 +292,7 @@ module Workflow
291
292
  prov_tree = prov_tree(dep_tree)
292
293
  if prov_tree && ! prov_tree.empty? && prov_tree.split("\n").length > 2
293
294
 
295
+ str.puts
294
296
  str.puts Log.color :magenta, "## DEPENDENCY GRAPH (abridged)"
295
297
  str.puts
296
298
  prov_tree.split("\n").each do |line|