rbbt-util 5.32.12 → 5.32.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rbbt/annotations/util.rb +1 -0
  3. data/lib/rbbt/entity.rb +6 -1
  4. data/lib/rbbt/hpc/batch.rb +3 -2
  5. data/lib/rbbt/hpc/orchestrate.rb +1 -0
  6. data/lib/rbbt/hpc/slurm.rb +2 -0
  7. data/lib/rbbt/resource/path.rb +6 -6
  8. data/lib/rbbt/tsv.rb +5 -0
  9. data/lib/rbbt/tsv/manipulate.rb +2 -0
  10. data/lib/rbbt/tsv/parallel/traverse.rb +9 -12
  11. data/lib/rbbt/util/R.rb +2 -2
  12. data/lib/rbbt/util/log.rb +15 -4
  13. data/lib/rbbt/util/log/progress/util.rb +2 -1
  14. data/lib/rbbt/util/misc/inspect.rb +1 -1
  15. data/lib/rbbt/util/misc/omics.rb +2 -2
  16. data/lib/rbbt/util/misc/system.rb +2 -2
  17. data/lib/rbbt/util/open.rb +1 -0
  18. data/lib/rbbt/util/python.rb +63 -3
  19. data/lib/rbbt/workflow.rb +54 -2
  20. data/lib/rbbt/workflow/accessor.rb +15 -242
  21. data/lib/rbbt/workflow/definition.rb +2 -1
  22. data/lib/rbbt/workflow/dependencies.rb +195 -0
  23. data/lib/rbbt/workflow/step.rb +10 -158
  24. data/lib/rbbt/workflow/step/accessor.rb +1 -311
  25. data/lib/rbbt/workflow/step/dependencies.rb +43 -3
  26. data/lib/rbbt/workflow/step/info.rb +294 -0
  27. data/lib/rbbt/workflow/step/status.rb +146 -0
  28. data/lib/rbbt/workflow/usage.rb +4 -2
  29. data/lib/rbbt/workflow/util/data.rb +35 -0
  30. data/lib/rbbt/workflow/util/orchestrator.rb +1 -1
  31. data/lib/rbbt/workflow/util/provenance.rb +40 -9
  32. data/python/rbbt.py +7 -0
  33. data/share/install/software/lib/install_helpers +1 -1
  34. data/share/rbbt_commands/hpc/orchestrate +4 -1
  35. data/share/rbbt_commands/hpc/task +2 -0
  36. data/share/rbbt_commands/lsf/orchestrate +4 -1
  37. data/share/rbbt_commands/lsf/task +2 -0
  38. data/share/rbbt_commands/slurm/orchestrate +4 -1
  39. data/share/rbbt_commands/slurm/task +2 -0
  40. data/share/rbbt_commands/system/clean +1 -0
  41. data/share/rbbt_commands/workflow/prov +1 -1
  42. data/test/rbbt/util/test_python.rb +3 -2
  43. data/test/rbbt/workflow/util/test_data.rb +48 -0
  44. metadata +9 -2
data/lib/rbbt/workflow.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rbbt/workflow/definition'
2
+ require 'rbbt/workflow/dependencies'
2
3
  require 'rbbt/workflow/task'
3
4
  require 'rbbt/workflow/step'
4
5
  require 'rbbt/workflow/accessor'
@@ -228,6 +229,47 @@ module Workflow
228
229
  end
229
230
  end
230
231
 
232
+ TAG = ENV["RBBT_INPUT_JOBNAME"] == "true" ? :inputs : :hash
233
+ DEBUG_JOB_HASH = ENV["RBBT_DEBUG_JOB_HASH"] == 'true'
234
+ def step_path(taskname, jobname, inputs, dependencies, extension = nil)
235
+ raise "Jobname makes an invalid path: #{ jobname }" if jobname.include? '..'
236
+ if inputs.length > 0 or dependencies.any?
237
+ tagged_jobname = case TAG
238
+ when :hash
239
+ clean_inputs = Annotated.purge(inputs)
240
+ clean_inputs = clean_inputs.collect{|i| Symbol === i ? i.to_s : i }
241
+ deps_str = dependencies.collect{|d| (Step === d || (defined?(RemoteStep) && RemoteStep === Step)) ? "Step: " << (d.overriden? ? d.path : d.short_path) : d }
242
+ key_obj = {:inputs => clean_inputs, :dependencies => deps_str }
243
+ key_str = Misc.obj2str(key_obj)
244
+ hash_str = Misc.digest(key_str)
245
+ Log.debug "Hash for '#{[taskname, jobname] * "/"}' #{hash_str} for #{key_str}" if DEBUG_JOB_HASH
246
+ jobname + '_' << hash_str
247
+ when :inputs
248
+ all_inputs = {}
249
+ inputs.zip(self.task_info(taskname)[:inputs]) do |i,f|
250
+ all_inputs[f] = i
251
+ end
252
+ dependencies.each do |dep|
253
+ ri = dep.recursive_inputs
254
+ ri.zip(ri.fields).each do |i,f|
255
+ all_inputs[f] = i
256
+ end
257
+ end
258
+
259
+ all_inputs.any? ? jobname + '_' << Misc.obj2str(all_inputs) : jobname
260
+ else
261
+ jobname
262
+ end
263
+ else
264
+ tagged_jobname = jobname
265
+ end
266
+
267
+ if extension and not extension.empty?
268
+ tagged_jobname = tagged_jobname + ('.' << extension.to_s)
269
+ end
270
+
271
+ workdir[taskname][tagged_jobname].find
272
+ end
231
273
  def import_task(workflow, orig, new)
232
274
  orig_task = workflow.tasks[orig]
233
275
  new_task = orig_task.dup
@@ -411,12 +453,22 @@ module Workflow
411
453
 
412
454
  overriden = has_overriden_inputs || overriden_deps.any?
413
455
 
456
+ extension = task.extension
457
+
458
+ if extension == :dep_task
459
+ extension = nil
460
+ if dependencies.any?
461
+ dep_basename = File.basename(dependencies.last.path)
462
+ extension = dep_basename.split(".").last if dep_basename.include?('.')
463
+ end
464
+ end
465
+
414
466
  if real_inputs.empty? && Workflow::TAG != :inputs && ! overriden
415
- step_path = step_path taskname, jobname, [], [], task.extension
467
+ step_path = step_path taskname, jobname, [], [], extension
416
468
  input_values = task.take_input_values(inputs)
417
469
  else
418
470
  input_values = task.take_input_values(inputs)
419
- step_path = step_path taskname, jobname, input_values, dependencies, task.extension
471
+ step_path = step_path taskname, jobname, input_values, dependencies, extension
420
472
  end
421
473
 
422
474
  job = get_job_step step_path, task, input_values, dependencies
@@ -7,7 +7,7 @@ module ComputeDependency
7
7
  dep.extend ComputeDependency
8
8
  dep.compute = value
9
9
  end
10
-
10
+
11
11
  def canfail?
12
12
  compute == :canfail || (Array === compute && compute.include?(:canfail))
13
13
  end
@@ -72,83 +72,6 @@ module Workflow
72
72
  end
73
73
  end
74
74
 
75
- def rec_dependencies(taskname)
76
- @rec_dependencies ||= {}
77
- @rec_dependencies[taskname] ||= begin
78
- if task_dependencies.include? taskname
79
-
80
- deps = task_dependencies[taskname]
81
-
82
- #all_deps = deps.select{|dep| String === dep or Symbol === dep or Array === dep}
83
-
84
- all_deps = []
85
- deps.each do |dep|
86
- if DependencyBlock === dep
87
- all_deps << dep.dependency if dep.dependency
88
- else
89
- all_deps << dep unless Proc === dep
90
- end
91
-
92
- begin
93
- case dep
94
- when Array
95
- wf, t, o = dep
96
-
97
- wf.rec_dependencies(t.to_sym).each do |d|
98
- if Array === d
99
- new = d.dup
100
- else
101
- new = [dep.first, d]
102
- end
103
-
104
- if Hash === o and not o.empty?
105
- if Hash === new.last
106
- hash = new.last.dup
107
- o.each{|k,v| hash[k] ||= v}
108
- new[new.length-1] = hash
109
- else
110
- new.push o.dup
111
- end
112
- end
113
-
114
- all_deps << new
115
- end if wf && t
116
-
117
- when String, Symbol
118
- rec_deps = rec_dependencies(dep.to_sym)
119
- all_deps.concat rec_deps
120
- when DependencyBlock
121
- dep = dep.dependency
122
- raise TryAgain
123
- end
124
- rescue TryAgain
125
- retry
126
- end
127
- end
128
- all_deps.uniq
129
- else
130
- []
131
- end
132
- end
133
- end
134
-
135
- def task_from_dep(dep)
136
- task = case dep
137
- when Array
138
- dep.first.tasks[dep[1]]
139
- when String
140
- tasks[dep.to_sym]
141
- when Symbol
142
- tasks[dep.to_sym]
143
- end
144
- raise "Unknown dependency: #{Misc.fingerprint dep}" if task.nil?
145
- task
146
- end
147
-
148
- #def rec_inputs(taskname)
149
- # [taskname].concat(rec_dependencies(taskname)).inject([]){|acc, tn| acc.concat(task_from_dep(tn).inputs) }.uniq
150
- #end
151
-
152
75
  def rec_inputs(taskname)
153
76
  task = task_from_dep(taskname)
154
77
  deps = rec_dependencies(taskname)
@@ -294,174 +217,24 @@ module Workflow
294
217
  _inputs
295
218
  end
296
219
 
297
- def override_dependencies(inputs)
298
- override_dependencies = IndiferentHash.setup({})
299
- return override_dependencies if inputs.nil?
300
- inputs.each do |key,value|
301
- if String === key && m = key.match(/(.*)#(.*)/)
302
- workflow, task = m.values_at 1, 2
303
- workflow = self.to_s if workflow.empty?
304
- override_dependencies[workflow] ||= IndiferentHash.setup({})
305
- override_dependencies[workflow][task] = value
306
- end
307
- end
308
- override_dependencies
309
- end
310
-
311
- def setup_override_dependency(dep, workflow, task_name)
312
- dep = Step === dep ? dep : Workflow.load_step(dep)
313
- dep.workflow = workflow
314
- dep.info[:name] = dep.name
315
- dep.original_task_name ||= dep.task_name if dep.workflow
316
- begin
317
- workflow = Kernel.const_get workflow if String === workflow
318
- dep.task = workflow.tasks[task_name] if dep.task.nil? && workflow.tasks.include?(task_name)
319
- rescue
320
- Log.exception $!
321
- end
322
- dep.task_name = task_name
323
- dep.overriden = dep.original_task_name.to_sym
324
- dep
325
- end
326
-
327
- def real_dependencies(task, orig_jobname, inputs, dependencies)
328
- real_dependencies = []
329
- path_deps = {}
330
-
331
- override_dependencies = override_dependencies(inputs)
332
-
333
- dependencies.each do |dependency|
334
- _inputs = IndiferentHash.setup(inputs.dup)
335
- jobname = orig_jobname
336
- jobname = _inputs[:jobname] if _inputs.include? :jobname
337
-
338
- real_dep = case dependency
339
- when Array
340
- workflow, dep_task, options = dependency
341
-
342
- if override_dependencies[workflow.to_s] && value = override_dependencies[workflow.to_s][dep_task]
343
- setup_override_dependency(value, workflow, dep_task)
344
- else
345
-
346
- compute = options[:compute] if options
347
-
348
- all_d = (real_dependencies + real_dependencies.flatten.collect{|d| d.rec_dependencies} ).flatten.compact.uniq
349
-
350
- _inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
351
- jobname = _inputs.delete :jobname if _inputs.include? :jobname
352
-
353
- job = workflow._job(dep_task, jobname, _inputs)
354
- ComputeDependency.setup(job, compute) if compute
355
- job
356
- end
357
- when Step
358
- dependency
359
- when Symbol
360
- if override_dependencies[self.to_s] && value = override_dependencies[self.to_s][dependency]
361
- setup_override_dependency(value, self, dependency)
362
- else
363
- _job(dependency, jobname, _inputs)
364
- end
365
- when Proc
366
- if DependencyBlock === dependency
367
- orig_dep = dependency.dependency
368
- wf, task_name, options = orig_dep
369
-
370
- options = {} if options.nil?
371
- compute = options[:compute]
372
-
373
- options = IndiferentHash.setup(options.dup)
374
- dep = dependency.call jobname, _inputs.merge(options), real_dependencies
375
-
376
- dep = [dep] unless Array === dep
377
-
378
- new_=[]
379
- dep.each{|d|
380
- next if d.nil?
381
- if Hash === d
382
- d[:workflow] ||= wf
383
- d[:task] ||= task_name
384
- _override_dependencies = override_dependencies.merge(override_dependencies(d[:inputs] || {}))
385
- d = if _override_dependencies[d[:workflow].to_s] && value = _override_dependencies[d[:workflow].to_s][d[:task]]
386
- setup_override_dependency(value, d[:workflow], d[:task])
387
- else
388
- task_info = d[:workflow].task_info(d[:task])
389
-
390
- _inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
391
- d[:workflow]._job(d[:task], d[:jobname], _inputs)
392
- end
393
- end
394
- ComputeDependency.setup(d, compute) if compute
395
- new_ << d
396
- }
397
- dep = new_
398
- else
399
- _inputs = IndiferentHash.setup(_inputs.dup)
400
- dep = dependency.call jobname, _inputs, real_dependencies
401
- if Hash === dep
402
- dep[:workflow] ||= wf || self
403
- _override_dependencies = override_dependencies.merge(override_dependencies(dep[:inputs] || {}))
404
- if _override_dependencies[dep[:workflow].to_s] && value = _override_dependencies[dep[:workflow].to_s][dep[:task]]
405
- setup_override_dependency(value, dep[:workflow], dep[:task])
406
- else
407
- task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
408
- _inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
409
- dep = dep[:workflow]._job(dep[:task], dep[:jobname], _inputs)
410
- end
411
- end
412
- end
413
-
414
- dep
415
- else
416
- raise "Dependency for #{task.name} not understood: #{Misc.fingerprint dependency}"
417
- end
418
-
419
- real_dependencies << real_dep
420
- end
421
- real_dependencies.flatten.compact
220
+ def task_from_dep(dep)
221
+ task = case dep
222
+ when Array
223
+ dep.first.tasks[dep[1]]
224
+ when String
225
+ tasks[dep.to_sym]
226
+ when Symbol
227
+ tasks[dep.to_sym]
228
+ end
229
+ raise "Unknown dependency: #{Misc.fingerprint dep}" if task.nil?
230
+ task
422
231
  end
423
232
 
424
- TAG = ENV["RBBT_INPUT_JOBNAME"] == "true" ? :inputs : :hash
425
- DEBUG_JOB_HASH = ENV["RBBT_DEBUG_JOB_HASH"] == 'true'
426
- def step_path(taskname, jobname, inputs, dependencies, extension = nil)
427
- raise "Jobname makes an invalid path: #{ jobname }" if jobname.include? '..'
428
- if inputs.length > 0 or dependencies.any?
429
- tagged_jobname = case TAG
430
- when :hash
431
- clean_inputs = Annotated.purge(inputs)
432
- clean_inputs = clean_inputs.collect{|i| Symbol === i ? i.to_s : i }
433
- deps_str = dependencies.collect{|d| (Step === d || (defined?(RemoteStep) && RemoteStep === Step)) ? "Step: " << d.short_path : d }
434
- key_obj = {:inputs => clean_inputs, :dependencies => deps_str }
435
- key_str = Misc.obj2str(key_obj)
436
- hash_str = Misc.digest(key_str)
437
- Log.debug "Hash for '#{[taskname, jobname] * "/"}' #{hash_str} for #{key_str}" if DEBUG_JOB_HASH
438
- jobname + '_' << hash_str
439
- when :inputs
440
- all_inputs = {}
441
- inputs.zip(self.task_info(taskname)[:inputs]) do |i,f|
442
- all_inputs[f] = i
443
- end
444
- dependencies.each do |dep|
445
- ri = dep.recursive_inputs
446
- ri.zip(ri.fields).each do |i,f|
447
- all_inputs[f] = i
448
- end
449
- end
450
-
451
- all_inputs.any? ? jobname + '_' << Misc.obj2str(all_inputs) : jobname
452
- else
453
- jobname
454
- end
455
- else
456
- tagged_jobname = jobname
457
- end
233
+ #def rec_inputs(taskname)
234
+ # [taskname].concat(rec_dependencies(taskname)).inject([]){|acc, tn| acc.concat(task_from_dep(tn).inputs) }.uniq
235
+ #end
458
236
 
459
- if extension and not extension.empty?
460
- tagged_jobname = tagged_jobname + ('.' << extension.to_s)
461
- end
462
237
 
463
- workdir[taskname][tagged_jobname].find
464
- end
465
238
 
466
239
  def id_for(path)
467
240
  if workdir.respond_to? :find
@@ -73,10 +73,11 @@ module Workflow
73
73
  REMOVE_DEP_TASKS = ENV["RBBT_REMOVE_DEP_TASKS"] == "true"
74
74
  def dep_task(name, workflow, oname, *rest, &block)
75
75
  dep(workflow, oname, *rest, &block)
76
- extension workflow.tasks[oname].extension if workflow.tasks.include?(oname) unless @extension
76
+ extension :dep_task unless @extension
77
77
  returns workflow.tasks[oname].result_description if workflow.tasks.include?(oname) unless @result_description
78
78
  task name do
79
79
  raise RbbtException, "dependency not found in dep_task" if dependencies.empty?
80
+ Step.wait_for_jobs dependencies
80
81
  dep = dependencies.last
81
82
  dep.join
82
83
  raise dep.get_exception if dep.error?
@@ -0,0 +1,195 @@
1
+ module Workflow
2
+ def rec_dependencies(taskname, seen = [])
3
+ @rec_dependencies ||= {}
4
+ @rec_dependencies[taskname] ||= [] unless task_dependencies.include?(taskname)
5
+ @rec_dependencies[taskname] ||= begin
6
+
7
+ deps = task_dependencies[taskname]
8
+
9
+ all_deps = []
10
+ deps.each do |dep|
11
+ next if seen.include?(dep)
12
+ if DependencyBlock === dep
13
+ all_deps << dep.dependency if dep.dependency
14
+ else
15
+ all_deps << dep unless Proc === dep
16
+ end
17
+
18
+ begin
19
+ case dep
20
+ when Array
21
+ wf, t, o = dep
22
+
23
+ wf.rec_dependencies(t.to_sym, seen + [dep]).each do |d|
24
+ if Array === d
25
+ new = d.dup
26
+ else
27
+ new = [dep.first, d]
28
+ end
29
+
30
+ if Hash === o and not o.empty?
31
+ if Hash === new.last
32
+ hash = new.last.dup
33
+ o.each{|k,v| hash[k] ||= v}
34
+ new[new.length-1] = hash
35
+ else
36
+ new.push o.dup
37
+ end
38
+ end
39
+
40
+ all_deps << new
41
+ end if wf && t
42
+
43
+ when String, Symbol
44
+ rec_deps = rec_dependencies(dep.to_sym, seen + [dep])
45
+ all_deps.concat rec_deps
46
+ when DependencyBlock
47
+ dep = dep.dependency
48
+ raise TryAgain
49
+ end
50
+ rescue TryAgain
51
+ retry
52
+ end
53
+ end
54
+ all_deps.uniq
55
+ end
56
+ end
57
+
58
+ def override_dependencies(inputs)
59
+ override_dependencies = IndiferentHash.setup({})
60
+ return override_dependencies if inputs.nil?
61
+ inputs.each do |key,value|
62
+ if String === key && m = key.match(/(.*)#(.*)/)
63
+ workflow, task = m.values_at 1, 2
64
+ workflow = self.to_s if workflow.empty?
65
+ override_dependencies[workflow] ||= IndiferentHash.setup({})
66
+ override_dependencies[workflow][task] = value
67
+ end
68
+ end
69
+ override_dependencies
70
+ end
71
+
72
+ def setup_override_dependency(dep, workflow, task_name)
73
+ return [] if dep == :skip || dep == 'skip'
74
+ dep = Step === dep ? dep : Workflow.load_step(dep)
75
+ dep.workflow = workflow
76
+ dep.info[:name] = dep.name
77
+ dep.original_task_name ||= dep.task_name if dep.workflow
78
+
79
+
80
+ begin
81
+ workflow = Kernel.const_get workflow if String === workflow
82
+ dep.task = workflow.tasks[task_name] if dep.task.nil? && workflow.tasks.include?(task_name)
83
+ rescue
84
+ Log.exception $!
85
+ end
86
+ dep.task_name = task_name
87
+ dep.overriden = dep.original_task_name.to_sym
88
+
89
+ dep.extend step_module
90
+
91
+ dep
92
+ end
93
+
94
+ def real_dependencies(task, orig_jobname, inputs, dependencies)
95
+ real_dependencies = []
96
+ path_deps = {}
97
+
98
+ override_dependencies = override_dependencies(inputs)
99
+
100
+ dependencies.each do |dependency|
101
+ _inputs = IndiferentHash.setup(inputs.dup)
102
+ jobname = orig_jobname
103
+ jobname = _inputs[:jobname] if _inputs.include? :jobname
104
+
105
+ real_dep = case dependency
106
+ when Array
107
+ workflow, dep_task, options = dependency
108
+
109
+ if override_dependencies[workflow.to_s] && value = override_dependencies[workflow.to_s][dep_task]
110
+ setup_override_dependency(value, workflow, dep_task)
111
+ else
112
+
113
+ compute = options[:compute] if options
114
+
115
+ all_d = (real_dependencies + real_dependencies.flatten.collect{|d| d.rec_dependencies} ).flatten.compact.uniq
116
+
117
+ _inputs = assign_dep_inputs(_inputs, options, all_d, workflow.task_info(dep_task))
118
+ jobname = _inputs.delete :jobname if _inputs.include? :jobname
119
+
120
+ job = workflow._job(dep_task, jobname, _inputs)
121
+ ComputeDependency.setup(job, compute) if compute
122
+ job
123
+ end
124
+ when Step
125
+ dependency
126
+ when Symbol
127
+ if override_dependencies[self.to_s] && value = override_dependencies[self.to_s][dependency]
128
+ setup_override_dependency(value, self, dependency)
129
+ else
130
+ _job(dependency, jobname, _inputs)
131
+ end
132
+ when Proc
133
+ if DependencyBlock === dependency
134
+ orig_dep = dependency.dependency
135
+ wf, task_name, options = orig_dep
136
+
137
+ if override_dependencies[wf.to_s] && value = override_dependencies[wf.to_s][task_name]
138
+ dep = setup_override_dependency(value, wf, task_name)
139
+ else
140
+
141
+ options = {} if options.nil?
142
+ compute = options[:compute]
143
+
144
+ options = IndiferentHash.setup(options.dup)
145
+ dep = dependency.call jobname, _inputs.merge(options), real_dependencies
146
+
147
+ dep = [dep] unless Array === dep
148
+
149
+ new_=[]
150
+ dep.each{|d|
151
+ next if d.nil?
152
+ if Hash === d
153
+ d[:workflow] ||= wf
154
+ d[:task] ||= task_name
155
+ _override_dependencies = override_dependencies.merge(override_dependencies(d[:inputs] || {}))
156
+ d = if _override_dependencies[d[:workflow].to_s] && value = _override_dependencies[d[:workflow].to_s][d[:task]]
157
+ setup_override_dependency(value, d[:workflow], d[:task])
158
+ else
159
+ task_info = d[:workflow].task_info(d[:task])
160
+
161
+ _inputs = assign_dep_inputs({}, options.merge(d[:inputs] || {}), real_dependencies, task_info)
162
+ d[:workflow]._job(d[:task], d[:jobname], _inputs)
163
+ end
164
+ end
165
+ ComputeDependency.setup(d, compute) if compute
166
+ new_ << d
167
+ }
168
+ dep = new_
169
+ end
170
+ else
171
+ _inputs = IndiferentHash.setup(_inputs.dup)
172
+ dep = dependency.call jobname, _inputs, real_dependencies
173
+ if Hash === dep
174
+ dep[:workflow] ||= wf || self
175
+ _override_dependencies = override_dependencies.merge(override_dependencies(dep[:inputs] || {}))
176
+ if _override_dependencies[dep[:workflow].to_s] && value = _override_dependencies[dep[:workflow].to_s][dep[:task]]
177
+ setup_override_dependency(value, dep[:workflow], dep[:task])
178
+ else
179
+ task_info = (dep[:task] && dep[:workflow]) ? dep[:workflow].task_info(dep[:task]) : nil
180
+ _inputs = assign_dep_inputs({}, dep[:inputs], real_dependencies, task_info)
181
+ dep = dep[:workflow]._job(dep[:task], dep[:jobname], _inputs)
182
+ end
183
+ end
184
+ end
185
+
186
+ dep
187
+ else
188
+ raise "Dependency for #{task.name} not understood: #{Misc.fingerprint dependency}"
189
+ end
190
+
191
+ real_dependencies << real_dep
192
+ end
193
+ real_dependencies.flatten.compact
194
+ end
195
+ end