scout-gear 10.7.1 → 10.7.3

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +50 -30
  3. data/VERSION +1 -1
  4. data/lib/scout/association/index.rb +5 -1
  5. data/lib/scout/association/item.rb +1 -1
  6. data/lib/scout/association.rb +46 -11
  7. data/lib/scout/entity/format.rb +9 -4
  8. data/lib/scout/entity/identifiers.rb +4 -4
  9. data/lib/scout/entity/named_array.rb +13 -0
  10. data/lib/scout/entity/property.rb +3 -1
  11. data/lib/scout/entity.rb +7 -4
  12. data/lib/scout/knowledge_base/enrichment.rb +9 -0
  13. data/lib/scout/knowledge_base/entity.rb +143 -0
  14. data/lib/scout/knowledge_base/list.rb +95 -0
  15. data/lib/scout/knowledge_base/query.rb +96 -0
  16. data/lib/scout/knowledge_base/registry.rb +173 -0
  17. data/lib/scout/knowledge_base/traverse.rb +329 -0
  18. data/lib/scout/knowledge_base.rb +91 -0
  19. data/lib/scout/persist/tsv/adapter/base.rb +13 -1
  20. data/lib/scout/persist/tsv.rb +2 -1
  21. data/lib/scout/tsv/annotation.rb +4 -4
  22. data/lib/scout/tsv/attach.rb +10 -2
  23. data/lib/scout/tsv/change_id.rb +3 -0
  24. data/lib/scout/tsv/dumper.rb +34 -30
  25. data/lib/scout/tsv/index.rb +0 -2
  26. data/lib/scout/tsv/open.rb +1 -0
  27. data/lib/scout/tsv/parser.rb +21 -10
  28. data/lib/scout/tsv/path.rb +8 -0
  29. data/lib/scout/tsv/stream.rb +17 -10
  30. data/lib/scout/tsv/traverse.rb +12 -2
  31. data/lib/scout/tsv/util/process.rb +4 -1
  32. data/lib/scout/tsv/util/select.rb +8 -2
  33. data/lib/scout/tsv/util/sort.rb +23 -15
  34. data/lib/scout/tsv/util.rb +11 -2
  35. data/lib/scout/tsv.rb +25 -11
  36. data/lib/scout/workflow/definition.rb +3 -3
  37. data/lib/scout/workflow/deployment/orchestrator.rb +8 -5
  38. data/lib/scout/workflow/step/dependencies.rb +35 -11
  39. data/lib/scout/workflow/step/file.rb +2 -1
  40. data/lib/scout/workflow/step/info.rb +23 -2
  41. data/lib/scout/workflow/step/load.rb +5 -3
  42. data/lib/scout/workflow/step/progress.rb +6 -0
  43. data/lib/scout/workflow/step/provenance.rb +1 -1
  44. data/lib/scout/workflow/step/status.rb +10 -4
  45. data/lib/scout/workflow/step.rb +32 -12
  46. data/lib/scout/workflow/task/dependencies.rb +33 -24
  47. data/lib/scout/workflow/task/inputs.rb +40 -12
  48. data/lib/scout/workflow/task.rb +22 -10
  49. data/lib/scout/workflow/usage.rb +2 -2
  50. data/lib/scout/workflow.rb +1 -1
  51. data/scout-gear.gemspec +28 -4
  52. data/scout_commands/kb/config +33 -0
  53. data/scout_commands/kb/entities +35 -0
  54. data/scout_commands/kb/list +39 -0
  55. data/scout_commands/kb/query +78 -0
  56. data/scout_commands/kb/register +44 -0
  57. data/scout_commands/kb/show +37 -0
  58. data/scout_commands/kb/traverse +66 -0
  59. data/test/data/person/brothers +1 -1
  60. data/test/scout/entity/test_identifiers.rb +3 -3
  61. data/test/scout/entity/test_named_array.rb +21 -0
  62. data/test/scout/knowledge_base/test_enrichment.rb +0 -0
  63. data/test/scout/knowledge_base/test_entity.rb +38 -0
  64. data/test/scout/knowledge_base/test_list.rb +40 -0
  65. data/test/scout/knowledge_base/test_query.rb +39 -0
  66. data/test/scout/knowledge_base/test_registry.rb +16 -0
  67. data/test/scout/knowledge_base/test_traverse.rb +245 -0
  68. data/test/scout/persist/test_tsv.rb +20 -0
  69. data/test/scout/persist/tsv/adapter/test_base.rb +20 -0
  70. data/test/scout/test_association.rb +17 -3
  71. data/test/scout/test_entity.rb +0 -15
  72. data/test/scout/test_knowledge_base.rb +27 -0
  73. data/test/scout/test_tsv.rb +40 -0
  74. data/test/scout/tsv/test_dumper.rb +24 -0
  75. data/test/scout/tsv/test_path.rb +24 -0
  76. data/test/scout/tsv/test_stream.rb +93 -0
  77. data/test/scout/tsv/test_traverse.rb +99 -0
  78. data/test/scout/tsv/test_util.rb +2 -0
  79. data/test/scout/tsv/util/test_select.rb +22 -0
  80. data/test/scout/tsv/util/test_sort.rb +24 -0
  81. data/test/scout/workflow/step/test_dependencies.rb +26 -0
  82. data/test/scout/workflow/step/test_info.rb +35 -0
  83. data/test/scout/workflow/task/test_dependencies.rb +67 -1
  84. data/test/scout/workflow/task/test_inputs.rb +24 -7
  85. data/test/scout/workflow/test_task.rb +36 -0
  86. data/test/scout/workflow/test_usage.rb +0 -1
  87. data/test/test_helper.rb +17 -0
  88. metadata +27 -3
data/lib/scout/tsv.rb CHANGED
@@ -16,7 +16,8 @@ require_relative 'tsv/csv'
16
16
 
17
17
  module TSV
18
18
  extend Annotation
19
- annotation :key_field, :fields, :type, :cast, :filename, :namespace, :unnamed, :identifiers, :serializer
19
+ annotation :key_field, :fields, :type, :cast, :filename, :namespace, :unnamed, :identifiers, :serializer, :entity_options
20
+
20
21
 
21
22
  def self.str2options(str)
22
23
  field_options,_sep, rest = str.partition("#")
@@ -34,7 +35,6 @@ module TSV
34
35
  alias original_setup setup
35
36
 
36
37
  def setup(obj, *rest, &block)
37
-
38
38
  if rest.length == 1 && String === rest.first
39
39
  options = TSV.str2options(rest.first)
40
40
  if Array === obj
@@ -44,7 +44,7 @@ module TSV
44
44
  when :single
45
45
  nil
46
46
  end
47
- obj = Misc.array2hash(obj, default_value)
47
+ obj = IndiferentHash.array2hash(obj, default_value)
48
48
  end
49
49
  original_setup(obj, options, &block)
50
50
  else
@@ -57,7 +57,7 @@ module TSV
57
57
  when :single
58
58
  nil
59
59
  end
60
- obj = Misc.array2hash(obj, default_value)
60
+ obj = IndiferentHash.array2hash(obj, default_value)
61
61
  end
62
62
  original_setup(obj, *rest, &block)
63
63
  end
@@ -74,11 +74,17 @@ module TSV
74
74
  end
75
75
 
76
76
  def self.open(file, options = {})
77
- grep, invert_grep, nocache, monitor, entity_options = IndiferentHash.process_options options, :grep, :invert_grep, :nocache, :monitor, :entity_options
77
+ grep, invert_grep, fixed_grep, nocache, monitor, entity_options, unnamed, field = IndiferentHash.process_options options, :grep, :invert_grep, :fixed_grep, :nocache, :monitor, :entity_options, :unnamed, :field
78
+
79
+ if field and options[:field].nil?
80
+ options[:fields] = [field]
81
+ options[:type] ||= :single
82
+ end
78
83
 
79
84
  persist_options = IndiferentHash.pull_keys options, :persist
80
85
  persist_options = IndiferentHash.add_defaults persist_options, prefix: "TSV", type: :HDB, persist: false
81
86
  persist_options[:data] ||= options[:data]
87
+ persist_options[:update] = options.delete(:update) if options.include?(:update)
82
88
 
83
89
  file = StringIO.new file if String === file && ! (Path === file) && file.index("\n")
84
90
 
@@ -113,14 +119,22 @@ module TSV
113
119
  end
114
120
 
115
121
  tsv = if TSV::Parser === file
116
- TSV.parse(file, **options)
117
- else
118
- options[:tsv_invert_grep] ||= invert_grep if invert_grep
119
- Open.open(file, grep: grep, invert_grep: invert_grep, nocache: nocache) do |f|
120
- TSV.parse(f, **options)
121
- end
122
+ TSV.parse(file, **options)
123
+ else
124
+ options[:tsv_invert_grep] ||= invert_grep if invert_grep
125
+ Open.open(file, grep: grep, invert_grep: invert_grep, fixed_grep: fixed_grep, nocache: nocache) do |f|
126
+ TSV.parse(f, **options)
127
+ end
128
+ end
129
+
130
+ if tsv.identifiers.nil? and Path === tsv.filename and tsv.filename.identifier_file_path
131
+ tsv.identifiers = tsv.filename.identifier_file_path.find if tsv.filename.identifier_file_path.exists?
122
132
  end
123
133
 
134
+ tsv.unnamed = unnamed unless unnamed.nil?
135
+
136
+ tsv.entity_options = entity_options
137
+
124
138
  tsv
125
139
  end
126
140
  end
@@ -164,9 +164,9 @@ module Workflow
164
164
  Step.wait_for_jobs dependencies.select{|d| d.streaming? }
165
165
  dep = dependencies.last
166
166
  dep.join
167
- raise dep.get_exception if dep.error?
167
+ raise dep.exception if dep.error?
168
168
  raise Aborted, "Aborted dependency #{dep.path}" if dep.aborted?
169
- set_info :type, dep.info[:type]
169
+ merge_info type: dep.info[:type], task_alias: true
170
170
 
171
171
  forget = config :forget_task_alias, "forget_task_alias"
172
172
  forget = config :forget_dep_tasks, "forget_dep_tasks", :default => FORGET_TASK_ALIAS if forget.nil?
@@ -181,7 +181,7 @@ module Workflow
181
181
  self.copy_linked_files_dir
182
182
  self.dependencies = self.dependencies - [dep]
183
183
  Open.rm_rf self.files_dir if Open.exist? self.files_dir
184
- FileUtils.cp_r dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
184
+ Open.link_dir dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
185
185
 
186
186
  if dep.overriden?
187
187
  Open.link dep.path, self.tmp_path
@@ -34,14 +34,16 @@ module Workflow
34
34
  end
35
35
 
36
36
  def self.job_rules(rules, job)
37
+ IndiferentHash.setup(rules)
37
38
  workflow = job.workflow.name
38
39
  task_name = job.task_name.to_s
39
40
  defaults = rules["defaults"] || {}
40
41
 
41
42
  return IndiferentHash.setup(defaults) unless rules[workflow]
42
- return IndiferentHash.setup(defaults) unless rules[workflow][task_name]
43
+ workflow_rules = IndiferentHash.setup(rules[workflow])
44
+ return IndiferentHash.setup(defaults) unless workflow_rules[task_name]
45
+ job_rules = IndiferentHash.setup(workflow_rules[task_name])
43
46
 
44
- job_rules = IndiferentHash.setup(rules[workflow][task_name])
45
47
  defaults.each{|k,v| job_rules[k] = v if job_rules[k].nil? } if defaults
46
48
  job_rules
47
49
  end
@@ -85,7 +87,7 @@ module Workflow
85
87
  candidates = workload.
86
88
  select{|k,v| v.empty? }.
87
89
  collect{|k,v| k }.
88
- reject{|k| k.done? || k.running? }
90
+ reject{|k| k.done? || k.running? || (k.error? && ! k.recoverable_error?) }
89
91
  else
90
92
  candidates = workload. #select{|k,v| Orchestrator.job_rules(rules, k) }.
91
93
  select{|k,v| v.empty? }.
@@ -107,7 +109,7 @@ module Workflow
107
109
 
108
110
  attr_accessor :available_resources, :resources_requested, :resources_used, :timer
109
111
 
110
- def initialize(timer = 5, available_resources = {})
112
+ def initialize(timer = 5, available_resources = nil)
111
113
  available_resources = {:cpus => Etc.nprocessors } if available_resources.nil?
112
114
  @timer = timer
113
115
  @available_resources = IndiferentHash.setup(available_resources)
@@ -192,7 +194,7 @@ module Workflow
192
194
  workload = Orchestrator.workload(jobs)
193
195
  all_jobs = workload.keys
194
196
 
195
- all_jobs.each{|job| job.clean unless job.done? && job.updated? }
197
+ all_jobs.each{|job| job.clean unless (job.done? && job.updated?) || (job.error? && ! job.recoverable_error?) }
196
198
 
197
199
  top_level_jobs = jobs.collect{|job| job.path }
198
200
  failed_jobs = []
@@ -216,6 +218,7 @@ module Workflow
216
218
  raise TryAgain
217
219
  end
218
220
  else
221
+ Log.warn "Non-recoverable error in #{job.path}"
219
222
  next
220
223
  end
221
224
  ensure
@@ -1,20 +1,26 @@
1
1
  class Step
2
2
  def rec_dependencies(connected = false, seen = [])
3
- direct_deps = []
4
- dependencies.each do |dep|
5
- next if seen.include? dep.path
6
- next if connected && dep.done? && dep.updated?
7
- direct_deps << dep
8
- end if dependencies
9
- seen.concat direct_deps.collect{|d| d.path }
10
- direct_deps.inject(direct_deps){|acc,d| acc.concat(d.rec_dependencies(connected, seen)); acc }
3
+ @rec_dependencies = {}
4
+ @rec_dependencies[connected] ||= begin
5
+ direct_deps = []
6
+ dependencies.each do |dep|
7
+ next if seen.include? dep.path
8
+ next if connected && dep.done? && dep.updated?
9
+ direct_deps << dep
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
16
+ end
11
17
  end
12
18
 
13
19
  def recursive_inputs
14
20
  recursive_inputs = NamedArray === inputs ? inputs.to_hash : {}
15
21
  return recursive_inputs if dependencies.nil?
16
22
  dependencies.inject(recursive_inputs) do |acc,dep|
17
- acc.merge(dep.recursive_inputs)
23
+ acc = dep.recursive_inputs.merge(acc)
18
24
  end
19
25
  end
20
26
 
@@ -41,6 +47,7 @@ class Step
41
47
  end
42
48
 
43
49
  next if dep.done?
50
+ next if dep.error? && ! dep.recoverable_error?
44
51
 
45
52
  if dep.dependencies
46
53
  dep.dependencies.each do |d|
@@ -72,9 +79,13 @@ class Step
72
79
  def run_dependencies
73
80
  all_dependencies.each do |dep|
74
81
  next if dep.running? || dep.done?
82
+ next if dep.error? && ! dep.recoverable_error?
83
+
75
84
  compute_options = compute[dep.path] if compute
76
85
  compute_options = [] if compute_options.nil?
77
86
 
87
+ next if compute_options.include?(false)
88
+
78
89
  stream = compute_options.include?(:stream)
79
90
  stream = true unless ENV["SCOUT_EXPLICIT_STREAMING"] == 'true'
80
91
  stream = :no_load if compute_options.include?(:produce)
@@ -95,12 +106,25 @@ class Step
95
106
  all_dependencies.each{|dep| dep.abort if dep.running? }
96
107
  end
97
108
 
98
- def self.wait_for_jobs(jobs)
109
+ def self.wait_for_jobs(jobs, canfail=false)
99
110
  threads = []
100
111
  jobs.each do |job|
101
112
  threads << Thread.new do
102
113
  Thread.current.report_on_exception = false
103
- job.join
114
+ begin
115
+ job.join
116
+ rescue Exception
117
+ case canfail
118
+ when TrueClass
119
+ next
120
+ else
121
+ if canfail === $!
122
+ next
123
+ else
124
+ raise $!
125
+ end
126
+ end
127
+ end
104
128
  end
105
129
  end
106
130
  threads.each do |t|
@@ -7,6 +7,7 @@ class Step
7
7
  else
8
8
  Path.setup(dir)
9
9
  end
10
+ dir = dir.find
10
11
  dir.pkgdir = self
11
12
  dir
12
13
  end
@@ -34,7 +35,7 @@ class Step
34
35
  begin
35
36
  realpath = Open.realpath(self.files_dir)
36
37
  Open.rm self.files_dir
37
- Open.cp realpath, self.files_dir
38
+ Open.link_dir realpath, self.files_dir
38
39
  rescue
39
40
  Log.warn "Copy files_dir for #{self.workflow_short_path} failed: " + $!.message
40
41
  end
@@ -24,7 +24,7 @@ class Step
24
24
  end
25
25
 
26
26
  def save_info(info = nil)
27
- Persist.save(info, info_file, SERIALIZER)
27
+ Persist.save(@info = info, info_file, SERIALIZER)
28
28
  @info_load_time = Time.now
29
29
  end
30
30
 
@@ -50,6 +50,15 @@ class Step
50
50
  @info
51
51
  end
52
52
 
53
+ def pid
54
+ info[:pid]
55
+ end
56
+
57
+ def pid=(pid)
58
+ set_info :pid, pid
59
+ end
60
+
61
+
53
62
  def merge_info(new_info)
54
63
  info = self.info
55
64
  new_info.each do |key,value|
@@ -121,6 +130,7 @@ class Step
121
130
  if message.nil?
122
131
  Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), Log.color(:path, path)] * " "
123
132
  else
133
+ message = Log.fingerprint(message.split("\n").first).sub(/^'/,'').sub(/'$/,'')
124
134
  Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), message, Log.color(:path, path)] * " "
125
135
  end
126
136
  end
@@ -143,6 +153,10 @@ class Step
143
153
  info[:messages]
144
154
  end
145
155
 
156
+ def message(message)
157
+ merge_info :message => message
158
+ end
159
+
146
160
  def status
147
161
  info[:status].tap{|s| s.nil? ? s : s.to_sym }
148
162
  end
@@ -165,7 +179,14 @@ class Step
165
179
  end
166
180
 
167
181
  def overriden_deps
168
- rec_dependencies.select{|d| d.overriden? }
182
+ dependencies.select{|d| d.overriden? }
183
+ end
184
+
185
+ def recursive_overriden_deps
186
+ overriden_deps = dependencies.select{|d|
187
+ d.overriden?
188
+ }
189
+ (overriden_deps + overriden_deps.collect{|d| d.recursive_overriden_deps }).flatten.uniq
169
190
  end
170
191
 
171
192
  def exception
@@ -4,9 +4,11 @@ class Step
4
4
  Path.setup(path) unless Path === path
5
5
  relocated = path.relocate
6
6
  return relocated if Open.exists?(relocated)
7
- subpath = path.split("/")[-3..-1] * "/"
8
- relocated = Path.setup("var/jobs")[subpath]
9
- return relocated if Open.exists?(relocated)
7
+ if path.scan("/").length >= 2
8
+ subpath = path.split("/")[-3..-1] * "/"
9
+ relocated = Path.setup("var/jobs")[subpath]
10
+ return relocated if Open.exists?(relocated)
11
+ end
10
12
  path
11
13
  end
12
14
 
@@ -19,5 +19,11 @@ class Step
19
19
  bar
20
20
  end
21
21
  end
22
+
23
+ def traverse(obj, desc: nil , **kwargs, &block)
24
+ desc = "Processing #{self.short_path}" if desc.nil?
25
+ kwargs[:bar] = self.progress_bar(desc) unless kwargs.include?(:bar)
26
+ TSV.traverse obj, **kwargs, &block
27
+ end
22
28
  end
23
29
 
@@ -62,7 +62,7 @@ class Step
62
62
  end
63
63
 
64
64
  if $inputs and $inputs.any?
65
- job_inputs = Workflow.load_step(path).recursive_inputs.to_hash
65
+ job_inputs = Step.new(path).recursive_inputs.to_hash
66
66
  IndiferentHash.setup(job_inputs)
67
67
 
68
68
  $inputs.each do |input|
@@ -20,11 +20,17 @@ class Step
20
20
  self.error? && ! (ScoutException === self.exception)
21
21
  end
22
22
 
23
- def updated?
24
- return false if self.error? && self.recoverable_error?
25
- return true if self.done? && ! ENV["SCOUT_UPDATE"]
23
+ def newer_dependencies
26
24
  newer = rec_dependencies.select{|dep| Path.newer?(self.path, dep.path) }
27
25
  newer += input_dependencies.select{|dep| Path.newer?(self.path, dep.path) }
26
+ newer += rec_dependencies.collect{|dep| dep.input_dependencies }.flatten.select{|dep| Path.newer?(self.path, dep.path) }
27
+ newer
28
+ end
29
+
30
+ def updated?
31
+ return false if self.error? && self.recoverable_error?
32
+ return true if (self.done? || (self.error? && ! self.recoverable_error?)) && ! ENV["SCOUT_UPDATE"]
33
+ newer = newer_dependencies
28
34
 
29
35
  Log.low "Newer deps found for #{Log.fingerprint self}: #{Log.fingerprint newer}" if newer.any?
30
36
  newer.empty?
@@ -56,7 +62,7 @@ class Step
56
62
  end
57
63
 
58
64
  def canfail?
59
- @compute && @compute.include?(:canfail)
65
+ @compute && @compute[self.path] && @compute[self.path].include?(:canfail)
60
66
  end
61
67
 
62
68
  def started?
@@ -138,18 +138,32 @@ class Step
138
138
 
139
139
  attr_reader :result
140
140
  def run(stream = false)
141
+ case stream
142
+ when TrueClass, :stream
143
+ no_load = :stream
144
+ when :no_load
145
+ no_load = true
146
+ else
147
+ no_load = false
148
+ end
149
+
150
+ if done?
151
+ if no_load
152
+ if no_load == :stream
153
+ return self.stream
154
+ else
155
+ return self.path
156
+ end
157
+ else
158
+ return @result || self.load
159
+ end
160
+ end
161
+
162
+
141
163
  return @result || self.load if done?
142
164
  prepare_dependencies
143
165
  begin
144
166
 
145
- case stream
146
- when TrueClass, :stream
147
- no_load = :stream
148
- when :no_load
149
- no_load = true
150
- else
151
- no_load = false
152
- end
153
167
 
154
168
  @result = Persist.persist(name, type, :path => path, :tee_copies => tee_copies, no_load: no_load) do
155
169
  input_names = (task.respond_to?(:inputs) && task.inputs) ? task.inputs.collect{|name,_| name} : []
@@ -206,6 +220,7 @@ class Step
206
220
  end
207
221
 
208
222
  @result.abort_callback = proc do |exception|
223
+ Open.rm self.path
209
224
  if exception.nil? || Aborted === exception || Interrupt === exception
210
225
  merge_info :status => :aborted, :end => Time.now
211
226
  else
@@ -240,6 +255,7 @@ class Step
240
255
  run(noload)
241
256
  end
242
257
  join
258
+ exit! 0
243
259
  end
244
260
  Process.detach pid
245
261
  grace
@@ -350,6 +366,10 @@ class Step
350
366
 
351
367
  def step(task_name)
352
368
  task_name = task_name.to_sym
369
+ dependencies.each do |dep|
370
+ return dep if dep.task_name && dep.task_name.to_sym == task_name
371
+ return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
372
+ end
353
373
  dependencies.each do |dep|
354
374
  return dep if dep.task_name && dep.task_name.to_sym == task_name
355
375
  return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
@@ -359,12 +379,12 @@ class Step
359
379
  nil
360
380
  end
361
381
 
362
- def short_path
363
- Resource.identify @path
382
+ def identify_path
383
+ Resource.identify path
364
384
  end
365
385
 
366
386
  def digest_str
367
- "Step: " + short_path
387
+ "Step: " + identify_path
368
388
  end
369
389
 
370
390
  def fingerprint
@@ -373,7 +393,7 @@ class Step
373
393
 
374
394
  def task_signature
375
395
  workflow_name = String === workflow ? workflow : workflow.name
376
- [workflow, task_name] * "#"
396
+ [workflow_name, task_name] * "#"
377
397
  end
378
398
 
379
399
  def alias?
@@ -9,22 +9,33 @@ module Task
9
9
  load_dep = proc do |id, workflow, task, step_options, definition_options, dependencies|
10
10
  task = step_options.delete(:task) if step_options.include?(:task)
11
11
  workflow = step_options.delete(:workflow) if step_options.include?(:workflow)
12
- id = step_options.delete(:id) if step_options.include?(:id)
13
- id = step_options.delete(:jobname) if step_options.include?(:jobname)
12
+
13
+ step_id = id
14
+ step_id = step_options.delete(:jobname) if step_options.include?(:jobname)
15
+ step_id = nil if step_id == Task::DEFAULT_NAME
14
16
 
15
17
  step_inputs = step_options.include?(:inputs)? step_options.delete(:inputs) : step_options
16
- step_inputs = IndiferentHash.add_defaults step_inputs, definition_options
18
+ step_inputs = IndiferentHash.add_defaults step_inputs.dup, definition_options
17
19
 
18
20
  resolved_inputs = {}
19
21
  step_inputs.each do |k,v|
20
22
  if Symbol === v
21
23
  input_dep = dependencies.select{|d| d.task_name == v }.first
22
- resolved_inputs[k] = input_dep || provided_inputs[v] || step_inputs[v] || v
24
+ resolved_inputs[k] = if input_dep
25
+ input_dep
26
+ elsif provided_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
27
+ provided_inputs[v]
28
+ elsif step_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
29
+ step_inputs[v]
30
+ else
31
+ v
32
+ end
23
33
  else
24
34
  resolved_inputs[k] = v
25
35
  end
26
36
  end
27
- job = workflow.job(task, id, resolved_inputs)
37
+
38
+ job = workflow.job(task, step_id, resolved_inputs)
28
39
  compute_options = definition_options[:compute] || []
29
40
  compute_options = [compute_options] unless Array === compute_options
30
41
  compute_options << :canfail if definition_options[:canfail]
@@ -33,26 +44,25 @@ module Task
33
44
  compute[job.path] = compute_options if compute_options.any?
34
45
 
35
46
  job.overriden = false if definition_options[:not_overriden]
47
+ job.compute = job.compute.nil? ? compute : job.compute.merge(compute)
36
48
 
37
49
  [job, step_inputs]
38
50
  end
39
51
 
40
52
  # Helper function
41
- find_dep_non_default_inputs = proc do |dep,definition_options,step_inputs={}|
53
+ filter_dep_non_default_inputs = proc do |dep,definition_options|
42
54
  dep_non_default_inputs = dep.non_default_inputs
43
- dep_non_default_inputs.select do |name|
44
- step_inputs.include?(name)
45
- end
46
55
  dep_non_default_inputs.reject! do |name|
47
- definition_options.include?(name) &&
48
- (definition_options[name] != :placeholder || definition_options[name] != dep.inputs[name])
56
+ definition_options.include?(name)
49
57
  end
50
58
 
51
59
  dep_non_default_inputs
52
60
  end
53
61
 
54
62
  deps.each do |workflow,task,definition_options,block=nil|
55
- definition_options[:id] = definition_options.delete(:jobname) if definition_options.include?(:jobname)
63
+ definition_options = definition_options.nil? ? {} : definition_options.dup
64
+
65
+ dep_id = definition_options.include?(:jobname) ? definition_options.delete(:jobname) : id
56
66
 
57
67
  if provided_inputs.include?(overriden = [workflow.name, task] * "#")
58
68
  dep = provided_inputs[overriden]
@@ -66,51 +76,50 @@ module Task
66
76
  next
67
77
  end
68
78
 
69
- definition_options ||= {}
70
79
 
71
80
  if block
72
- fixed_provided_inputs = self.assign_inputs(provided_inputs).first.to_hash
73
- self.inputs.each do |name,type,desc,value|
81
+ fixed_provided_inputs = self.assign_inputs(provided_inputs, dep_id).first.to_hash
82
+ self.inputs.each do |name,type,desc,value,options|
74
83
  fixed_provided_inputs[name] = value unless fixed_provided_inputs.include?(name)
75
84
  end
76
85
  fixed_provided_inputs = IndiferentHash.add_defaults fixed_provided_inputs, provided_inputs
77
86
  block_options = IndiferentHash.add_defaults definition_options.dup, fixed_provided_inputs
78
87
 
79
- res = block.call id, block_options, dependencies
88
+ res = block.call dep_id, block_options, dependencies
80
89
 
81
90
  case res
82
91
  when Step
83
92
  dep = res
84
93
  dependencies << dep
85
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
94
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
86
95
  non_default_inputs.concat(dep_non_default_inputs)
87
96
  when Hash
88
97
  step_options = block_options.merge(res)
89
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
98
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
90
99
  dependencies << dep
91
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
100
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
92
101
  non_default_inputs.concat(dep_non_default_inputs)
93
102
  when Array
94
103
  res.each do |_res|
95
104
  if Hash === _res
96
105
  step_options = block_options.merge(_res)
97
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
106
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
98
107
  dependencies << dep
99
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
108
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
100
109
  non_default_inputs.concat(dep_non_default_inputs)
101
110
  else
102
111
  dep = _res
103
112
  dependencies << dep
104
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
113
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
105
114
  non_default_inputs.concat(dep_non_default_inputs)
106
115
  end
107
116
  end
108
117
  end
109
118
  else
110
119
  step_options = IndiferentHash.add_defaults definition_options.dup, provided_inputs
111
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, definition_options, dependencies)
120
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options, definition_options, dependencies)
112
121
  dependencies << dep
113
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
122
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
114
123
  non_default_inputs.concat(dep_non_default_inputs)
115
124
  end
116
125
  end