rbbt-util 5.32.23 → 5.32.27

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: 900a7061d40ec2cbffd38886ef9629aa0c0ed6d6ee1aef6e0c95c51656230ef0
4
- data.tar.gz: 13b965a0ec134a932c6ae0ae6a109fbc2bc83b7ffd855a1ef05ed4e1e51b9d88
3
+ metadata.gz: ffa357551766aa6ae6da35c586949c0ff05814171304ca5a874689418c7c48e2
4
+ data.tar.gz: 5e1e419fcf846fc8ead12a77e6713f198a74d516c0262c34b4d86380a58af092
5
5
  SHA512:
6
- metadata.gz: 3b890e2b6fb3675df4319d0541d9057a54b0cb37286a814822915f5b5b061d4f7e02deab0afdd7cd0833cb741aeded7454a9585f93ff3486e595b99db4da00f6
7
- data.tar.gz: 105072ca6c7b5c43c6a60455eaa9c7167feeb93f505c61c6aeffe6305de3166a6cb440c262abf025407306ba82c2fe3167f5f9e743e086d99fa936e44ea8e448
6
+ metadata.gz: a6afd86e7698e5b7e4588412ed678497c825242616bc75d2fa2ab835bc325a8a58826da164dea16cd5b4bbf81697ac5201bb347af220bab5ce238f8e0ce4edcb
7
+ data.tar.gz: 3e86fe7c2d84cc7a04cdd348f03a6323b5467723182057ec028b5d611b3dd200fce41949f1502ca59b0a295b5664f1d6ba259d27a196039f873261e9faf7a1a6
data/bin/rbbt CHANGED
@@ -262,9 +262,8 @@ rescue ParameterException
262
262
  puts
263
263
  exit_status = -1
264
264
  exit exit_status
265
- rescue SystemExit
266
- rescue CmdStop
267
- exit_status = $!.exit_status
265
+ rescue SystemExit,CmdStop
266
+ exit_status = $!.status
268
267
  exit exit_status
269
268
  rescue Exception
270
269
  Log.exception $!
data/bin/rbbt_find.rb ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbbt-util'
4
+ require 'rbbt/util/simpleopt'
5
+
6
+ $0 = "rbbt #{$previous_commands*" "} #{ File.basename(__FILE__) }" if $previous_commands
7
+
8
+ options = SOPT.setup <<EOF
9
+
10
+ Find a path
11
+
12
+ $ #{$0} [options] [<subpath>] <path>
13
+
14
+ Use - to read from STDIN
15
+
16
+ -h--help Print this help
17
+ -w--workflows Workflow to load
18
+ -s--search_path* Workflow to load
19
+ -l--list List contents of resolved directories
20
+ -n--nocolor Don't color output
21
+ EOF
22
+ if options[:help]
23
+ if defined? rbbt_usage
24
+ rbbt_usage
25
+ else
26
+ puts SOPT.doc
27
+ end
28
+ exit 0
29
+ end
30
+
31
+ subpath, path = ARGV
32
+ path, subpath = subpath, nil if path.nil?
33
+
34
+ begin
35
+ require 'rbbt/workflow'
36
+ workflow = Workflow.require_workflow subpath
37
+ subpath = workflow.libdir
38
+ rescue
39
+ Log.exception $!
40
+ end if subpath && subpath =~ /^[A-Z][a-zA-Z]+$/
41
+
42
+ path = subpath ? Path.setup(subpath)[path] : Path.setup(path)
43
+
44
+ search_path = options[:search_path].to_sym if options.include? :search_path
45
+ nocolor = options[:nocolor]
46
+
47
+ found = if search_path
48
+ [path.find(search_path)]
49
+ else
50
+ path.find_all
51
+ end
52
+
53
+ found.each do |path|
54
+ if options[:list] && File.directory?(path)
55
+ puts Log.color :blue, path
56
+ path.glob("*").each do |subpath|
57
+ if nocolor
58
+ puts subpath
59
+ else
60
+ color = File.directory?(subpath) ? :blue : nil
61
+ puts " " << Log.color(color, subpath)
62
+ end
63
+ end
64
+ else
65
+ if nocolor
66
+ puts path
67
+ else
68
+ color = File.exists?(path) ? (File.directory?(path) ? :blue : nil) : :red
69
+ puts Log.color color, path
70
+ end
71
+
72
+ end
73
+ end
74
+
@@ -51,6 +51,7 @@ export BATCH_SYSTEM=SLURM
51
51
  "nodes" => nodes,
52
52
  "time" => time,
53
53
  "exclusive" => exclusive,
54
+ "highmem" => highmem,
54
55
  "licenses" => licenses,
55
56
  "gres" => gres,
56
57
  "mem" => mem,
@@ -177,7 +177,7 @@ module TSV
177
177
 
178
178
  sheet ||= "0"
179
179
  workbook = RubyXL::Parser.parse file
180
- if sheet && sheet =~ /^\d+$/
180
+ if sheet && sheet =~ /^\d+$/
181
181
  sheet = workbook.worksheets.collect{|s| s.sheet_name }[sheet.to_i]
182
182
  end
183
183
  sheet_name = sheet
@@ -185,7 +185,9 @@ module TSV
185
185
 
186
186
  TmpFile.with_file :extension => Misc.sanitize_filename(sheet_name.to_s) do |filename|
187
187
 
188
- sheet = sheet ? workbook[sheet] : workbook.worksheets.first
188
+ sheet = sheet_name ? workbook[sheet_name] : workbook.worksheets.first
189
+
190
+ raise "No sheet #{sheet_name} found" if sheet.nil?
189
191
 
190
192
  rows = []
191
193
 
@@ -217,21 +219,27 @@ module TSV
217
219
  end
218
220
 
219
221
  def self.write(tsv, file, options = {})
220
- sheet = Misc.process_options options, :sheet
222
+ sheet, add_sheet = Misc.process_options options, :sheet, :add_sheet
221
223
 
222
224
  fields, rows = TSV._excel_data(tsv, options)
223
225
 
224
- book = RubyXL::Workbook.new
225
- sheet1 = book.worksheets.first
226
- sheet1.sheet_name = sheet if sheet
226
+ if Open.exists?(file) && add_sheet
227
+ book = RubyXL::Parser.parse file
228
+ sheet1 = book.add_worksheet(sheet)
229
+ else
230
+ book = RubyXL::Workbook.new
231
+ sheet1 = book.worksheets.first
232
+ sheet1.sheet_name = sheet if sheet
233
+ end
227
234
 
228
235
  fields.each_with_index do |e,i|
229
236
  sheet1.add_cell(0, i, e)
230
- end
237
+ end if fields
231
238
 
232
239
  rows.each_with_index do |cells,i|
240
+ i += 1 if fields
233
241
  cells.each_with_index do |e,j|
234
- sheet1.add_cell(i+1, j, e)
242
+ sheet1.add_cell(i, j, e)
235
243
  end
236
244
  end
237
245
 
@@ -356,6 +356,16 @@ module TSV
356
356
  elems.sort_by{|k,v| v}.collect{|k,v| k}
357
357
  end
358
358
 
359
+ def subset(keys)
360
+ new = TSV.setup({}, :key_field => key_field, :fields => fields, :type => type, :filename => filename, :identifiers => identifiers)
361
+ self.with_unnamed do
362
+ keys.each do |k|
363
+ new[k] = self[k]
364
+ end
365
+ end
366
+ new
367
+ end
368
+
359
369
  def select(method = nil, invert = false, &block)
360
370
  new = TSV.setup({}, :key_field => key_field, :fields => fields, :type => type, :filename => filename, :identifiers => identifiers)
361
371
 
@@ -76,7 +76,7 @@ module Workflow
76
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
- raise RbbtException, "dependency not found in dep_task" if dependencies.empty?
79
+ raise RbbtException, "dep_task does not have any dependencies" if dependencies.empty?
80
80
  Step.wait_for_jobs dependencies.select{|d| d.streaming? }
81
81
  dep = dependencies.last
82
82
  dep.join
@@ -25,71 +25,6 @@ module Workflow
25
25
  end.compact
26
26
  end
27
27
 
28
- def self.load_inputs(dir, input_names, input_types)
29
- inputs = {}
30
- if File.exists?(dir) && ! File.directory?(dir)
31
- Log.debug "Loading inputs from #{dir}, not a directory trying as tar.gz"
32
- tarfile = dir
33
- digest = CMD.cmd("md5sum '#{tarfile}'").read.split(" ").first
34
- tmpdir = Rbbt.tmp.input_bundle[digest].find
35
- Misc.untar(tarfile, tmpdir) unless File.exists? tmpdir
36
- files = tmpdir.glob("*")
37
- if files.length == 1 && File.directory?(files.first)
38
- tmpdir = files.first
39
- end
40
- load_inputs(tmpdir, input_names, input_types)
41
- else
42
- dir = Path.setup(dir.dup)
43
- input_names.each do |input|
44
- file = dir[input].find
45
- file = dir.glob(input.to_s + ".*").reject{|f| f =~ /\.md5$/}.first if file.nil? or not file.exists?
46
- Log.debug "Trying #{ input }: #{file}"
47
- next unless file and file.exists?
48
-
49
-
50
- case input_types[input]
51
- when :file
52
- Log.debug "Pointing #{ input } to #{file}"
53
- if file =~ /\.yaml/
54
- inputs[input.to_sym] = YAML.load(Open.read(file))
55
- else
56
- if File.symlink?(file)
57
- link_target = File.expand_path(File.readlink(file), File.dirname(file))
58
- inputs[input.to_sym] = link_target
59
- else
60
- inputs[input.to_sym] = Open.realpath(file)
61
- end
62
- end
63
- when :text
64
- Log.debug "Reading #{ input } from #{file}"
65
- inputs[input.to_sym] = Open.read(file)
66
- when :array
67
- Log.debug "Reading array #{ input } from #{file}"
68
- inputs[input.to_sym] = Open.read(file).split("\n")
69
- when :tsv
70
- Log.debug "Opening tsv #{ input } from #{file}"
71
- inputs[input.to_sym] = TSV.open(file)
72
- when :boolean
73
- inputs[input.to_sym] = (file.read.strip == 'true')
74
- else
75
- Log.debug "Loading #{ input } from #{file}"
76
- inputs[input.to_sym] = file.read.strip
77
- end
78
-
79
- end
80
- inputs = IndiferentHash.setup(inputs)
81
-
82
- dir.glob("*#*").each do |od|
83
- name = File.basename(od)
84
- value = Open.read(od)
85
- Log.debug "Loading override dependency #{ name } as #{value}"
86
- inputs[name] = value.chomp
87
- end
88
-
89
- inputs
90
- end
91
- end
92
-
93
28
  def example_inputs(task_name, example)
94
29
  inputs = {}
95
30
  IndiferentHash.setup(inputs)
@@ -86,76 +86,6 @@ class Step
86
86
  end
87
87
  end
88
88
 
89
- def self.save_inputs(inputs, input_types, dir)
90
- inputs.each do |name,value|
91
- type = input_types[name]
92
- type = type.to_s if type
93
- path = File.join(dir, name.to_s)
94
-
95
- Log.debug "Saving job input #{name} (#{type}) into #{path}"
96
- case
97
- when Step === value
98
- Open.ln_s(value.path, path)
99
- when type.to_s == "file"
100
- if String === value && File.exists?(value)
101
- value = File.expand_path(value)
102
- Open.ln_s(value, path)
103
- else
104
- value = value.collect{|v| v = "#{v}" if Path === v; v }if Array === value
105
- value = "#{value}" if Path === value
106
- Open.write(path + '.yaml', value.to_yaml)
107
- end
108
- when Array === value
109
- Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
110
- when IO === value
111
- if value.filename && String === value.filename && File.exists?(value.filename)
112
- Open.ln_s(value.filename, path)
113
- else
114
- Open.write(path, value)
115
- end
116
- else
117
- Open.write(path, value.to_s)
118
- end
119
- end.any?
120
- end
121
-
122
- def self.save_job_inputs(job, dir, options = nil)
123
- options = IndiferentHash.setup options.dup if options
124
-
125
- task_name = Symbol === job.overriden ? job.overriden : job.task_name
126
- workflow = job.workflow
127
- workflow = Kernel.const_get workflow if String === workflow
128
- if workflow
129
- task_info = IndiferentHash.setup(workflow.task_info(task_name))
130
- input_types = IndiferentHash.setup(task_info[:input_types])
131
- task_inputs = IndiferentHash.setup(task_info[:inputs])
132
- input_defaults = IndiferentHash.setup(task_info[:input_defaults])
133
- else
134
- task_info = IndiferentHash.setup({})
135
- input_types = IndiferentHash.setup({})
136
- task_inputs = IndiferentHash.setup({})
137
- input_defaults = IndiferentHash.setup({})
138
- end
139
-
140
- inputs = IndiferentHash.setup({})
141
- real_inputs = job.real_inputs || job.info[:real_inputs]
142
- job.recursive_inputs.zip(job.recursive_inputs.fields).each do |value,name|
143
- next unless task_inputs.include? name.to_sym
144
- next unless real_inputs.include? name.to_sym
145
- next if options && ! options.include?(name)
146
- next if value.nil?
147
- next if input_defaults[name] == value
148
- inputs[name] = value
149
- end
150
-
151
- if options && options.include?('override_dependencies')
152
- inputs.merge!(:override_dependencies => open[:override_dependencies])
153
- input_types = IndiferentHash.setup(input_types.merge(:override_dependencies => :array))
154
- end
155
- save_inputs(inputs, input_types, dir)
156
-
157
- inputs.keys
158
- end
159
89
 
160
90
  def name
161
91
  @name ||= path.sub(/.*\/#{Regexp.quote task_name.to_s}\/(.*)/, '\1')
@@ -254,7 +254,12 @@ class Step
254
254
  when :bootstrap
255
255
  cpus = rest.nil? ? nil : rest.first
256
256
 
257
- cpus = config('dep_cpus', 'bootstrap', :default => [5, list.length / 2].min) if cpus.nil? || cpus.to_i == 0
257
+ if cpus.nil?
258
+ keys = ['bootstrap'] + list.collect{|d| [d.task_name, d.task_signature] }.flatten.uniq
259
+ cpus = config('dep_cpus', *keys, :default => [5, list.length / 2].min)
260
+ elsif Symbol === cpus
261
+ cpus = config('dep_cpus', cpus, :default => [5, list.length / 2].min)
262
+ end
258
263
 
259
264
  respawn = rest && rest.include?(:respawn)
260
265
  respawn = false if rest && rest.include?(:norespawn)
@@ -369,7 +374,8 @@ class Step
369
374
  next unless step.dependencies and step.dependencies.any?
370
375
  (step.dependencies + step.input_dependencies).each do |step_dep|
371
376
  next unless step.dependencies.include?(step_dep)
372
- next if step_dep.done? or step_dep.running? or (ComputeDependency === step_dep and (step_dep.compute == :nodup or step_dep.compute == :ignore))
377
+ next if step_dep.done? or step_dep.running? or
378
+ (ComputeDependency === step_dep and (step_dep.compute == :nodup or step_dep.compute == :ignore))
373
379
  dep_step[step_dep.path] ||= []
374
380
  dep_step[step_dep.path] << step
375
381
  end
@@ -0,0 +1,162 @@
1
+ module Workflow
2
+ def self.load_inputs(dir, input_names, input_types)
3
+ inputs = {}
4
+ if File.exists?(dir) && ! File.directory?(dir)
5
+ Log.debug "Loading inputs from #{dir}, not a directory trying as tar.gz"
6
+ tarfile = dir
7
+ digest = CMD.cmd("md5sum '#{tarfile}'").read.split(" ").first
8
+ tmpdir = Rbbt.tmp.input_bundle[digest].find
9
+ Misc.untar(tarfile, tmpdir) unless File.exists? tmpdir
10
+ files = tmpdir.glob("*")
11
+ if files.length == 1 && File.directory?(files.first)
12
+ tmpdir = files.first
13
+ end
14
+ load_inputs(tmpdir, input_names, input_types)
15
+ else
16
+ dir = Path.setup(dir.dup)
17
+ input_names.each do |input|
18
+ file = dir[input].find
19
+ file = dir.glob(input.to_s + ".*").reject{|f| f =~ /\.md5$/}.first if file.nil? or not (File.symlink?(file) || file.exists?)
20
+ Log.debug "Trying #{ input }: #{file}"
21
+ next unless file and (File.symlink?(file) || file.exists?)
22
+
23
+ type = input_types[input]
24
+
25
+ type = :io if file.split(".").last == 'as_io'
26
+
27
+ case type
28
+ when :io
29
+ inputs[input.to_sym] = Open.open(Open.realpath(file))
30
+ when :file, :binary
31
+ Log.debug "Pointing #{ input } to #{file}"
32
+ if file =~ /\.yaml/
33
+ inputs[input.to_sym] = YAML.load(Open.read(file))
34
+ else
35
+ if File.symlink?(file)
36
+ link_target = File.expand_path(File.readlink(file), File.dirname(file))
37
+ inputs[input.to_sym] = link_target
38
+ else
39
+ inputs[input.to_sym] = Open.realpath(file)
40
+ end
41
+ end
42
+ when :text
43
+ Log.debug "Reading #{ input } from #{file}"
44
+ inputs[input.to_sym] = Open.read(file)
45
+ when :array
46
+ Log.debug "Reading array #{ input } from #{file}"
47
+ inputs[input.to_sym] = Open.read(file).split("\n")
48
+ when :tsv
49
+ Log.debug "Opening tsv #{ input } from #{file}"
50
+ inputs[input.to_sym] = TSV.open(file)
51
+ when :boolean
52
+ inputs[input.to_sym] = (file.read.strip == 'true')
53
+ else
54
+ Log.debug "Loading #{ input } from #{file}"
55
+ inputs[input.to_sym] = file.read.strip
56
+ end
57
+
58
+ end
59
+ inputs = IndiferentHash.setup(inputs)
60
+
61
+ dir.glob("*#*").each do |od|
62
+ name = File.basename(od)
63
+ value = Open.read(od)
64
+ Log.debug "Loading override dependency #{ name } as #{value}"
65
+ inputs[name] = value.chomp
66
+ end
67
+
68
+ inputs
69
+ end
70
+ end
71
+
72
+ def task_inputs_from_directory(task_name, directory)
73
+ task_info = self.task_info(task_name)
74
+ Workflow.load_inputs(directory, task_info[:inputs], task_info[:input_types])
75
+ end
76
+
77
+ def job_for_directory_inputs(task_name, directory, jobname = nil)
78
+ inputs = task_inputs_from_directory(task_name, directory)
79
+ job(task_name, jobname, inputs)
80
+ end
81
+
82
+ end
83
+
84
+ class Step
85
+ def self.save_inputs(inputs, input_types, input_options, dir)
86
+ inputs.each do |name,value|
87
+ type = input_types[name]
88
+ type = type.to_s if type
89
+ path = File.join(dir, name.to_s)
90
+
91
+ path = path + '.as_io' if (IO === value || Step === value) && ! (input_options[name] && input_options[name][:nofile])
92
+ Log.debug "Saving job input #{name} (#{type}) into #{path}"
93
+
94
+ case
95
+ when IO === value
96
+ Open.write(path, value.to_s)
97
+ when Step === value
98
+ Open.ln_s(value.path, path)
99
+ when type.to_s == "file"
100
+ if String === value && File.exists?(value)
101
+ value = File.expand_path(value)
102
+ Open.ln_s(value, path)
103
+ else
104
+ value = value.collect{|v| v = "#{v}" if Path === v; v }if Array === value
105
+ value = "#{value}" if Path === value
106
+ Open.write(path + '.yaml', value.to_yaml)
107
+ end
108
+ when Array === value
109
+ Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
110
+ when IO === value
111
+ if value.filename && String === value.filename && File.exists?(value.filename)
112
+ Open.ln_s(value.filename, path)
113
+ else
114
+ Open.write(path, value)
115
+ end
116
+ else
117
+ Open.write(path, value.to_s)
118
+ end
119
+ end.any?
120
+ end
121
+
122
+ def self.save_job_inputs(job, dir, options = nil)
123
+ options = IndiferentHash.setup options.dup if options
124
+
125
+ task_name = Symbol === job.overriden ? job.overriden : job.task_name
126
+ workflow = job.workflow
127
+ workflow = Kernel.const_get workflow if String === workflow
128
+ if workflow
129
+ task_info = IndiferentHash.setup(workflow.task_info(task_name))
130
+ input_types = IndiferentHash.setup(task_info[:input_types])
131
+ input_options = IndiferentHash.setup(task_info[:input_options])
132
+ task_inputs = IndiferentHash.setup(task_info[:inputs])
133
+ input_defaults = IndiferentHash.setup(task_info[:input_defaults])
134
+ else
135
+ task_info = IndiferentHash.setup({})
136
+ input_types = IndiferentHash.setup({})
137
+ task_inputs = IndiferentHash.setup({})
138
+ task_options = IndiferentHash.setup({})
139
+ input_defaults = IndiferentHash.setup({})
140
+ end
141
+
142
+ inputs = IndiferentHash.setup({})
143
+ real_inputs = job.real_inputs || job.info[:real_inputs]
144
+ job.recursive_inputs.zip(job.recursive_inputs.fields).each do |value,name|
145
+ next unless task_inputs.include? name.to_sym
146
+ next unless real_inputs.include? name.to_sym
147
+ next if options && ! options.include?(name)
148
+ next if value.nil?
149
+ next if input_defaults[name] == value
150
+ inputs[name] = value
151
+ end
152
+
153
+ if options && options.include?('override_dependencies')
154
+ inputs.merge!(:override_dependencies => open[:override_dependencies])
155
+ input_types = IndiferentHash.setup(input_types.merge(:override_dependencies => :array))
156
+ end
157
+
158
+ save_inputs(inputs, input_types, input_options, dir)
159
+
160
+ inputs.keys
161
+ end
162
+ end
@@ -6,6 +6,7 @@ require 'rbbt/workflow/step/accessor'
6
6
  require 'rbbt/workflow/step/prepare'
7
7
  require 'rbbt/workflow/step/status'
8
8
  require 'rbbt/workflow/step/info'
9
+ require 'rbbt/workflow/step/save_load_inputs'
9
10
 
10
11
  class Step
11
12
  attr_accessor :clean_name, :path, :task, :workflow, :inputs, :dependencies, :bindings
@@ -321,7 +322,7 @@ class Step
321
322
  def load
322
323
  res = begin
323
324
  @result = nil if IO === @result && @result.closed?
324
- if @result && @path != @result
325
+ if @result && @path != @result && ! StreamArray === @result
325
326
  res = @result
326
327
  else
327
328
  join if not done?
@@ -90,11 +90,11 @@ module Task
90
90
 
91
91
  maps = (Array === dep and Hash === dep.last) ? dep.last.keys : []
92
92
  raise "Dependency task not found: #{dep}" if task.nil?
93
- next if seen.include? [wf, task.name]
93
+ next if seen.include? [wf, task.name, maps]
94
94
 
95
95
  task.workflow = wf if wf
96
96
 
97
- seen << [wf, task.name]
97
+ seen << [wf, task.name, maps]
98
98
  new_inputs = task.inputs - maps
99
99
  next unless new_inputs.any?
100
100
  if task_inputs[task].nil?
data/lib/rbbt/workflow.rb CHANGED
@@ -45,14 +45,10 @@ module Workflow
45
45
  load_remote_tasks(Rbbt.root.etc.remote_tasks.find) if Rbbt.root.etc.remote_tasks.exists?
46
46
  end
47
47
 
48
- def self.require_remote_workflow(wf_name, url)
49
- require 'rbbt/workflow/remote_workflow'
50
- eval "Object::#{wf_name} = RemoteWorkflow.new '#{ url }', '#{wf_name}'"
51
- end
52
48
 
53
49
  def self.require_remote_workflow(wf_name, url)
54
50
  require 'rbbt/workflow/remote_workflow'
55
- eval "Object::#{wf_name} = RemoteWorkflow.new '#{ url }', '#{wf_name}'"
51
+ eval "Object::#{wf_name.split("+").first} = RemoteWorkflow.new '#{ url }', '#{wf_name}'"
56
52
  end
57
53
 
58
54
  def self.load_workflow_libdir(filename)
@@ -134,9 +130,10 @@ module Workflow
134
130
  end
135
131
 
136
132
  def self.require_local_workflow(wf_name)
133
+
137
134
  filename = local_workflow_filename(wf_name)
138
135
 
139
- if filename and File.exist? filename
136
+ if filename and File.exist?(filename)
140
137
  load_workflow_file filename
141
138
  else
142
139
  return false
@@ -194,14 +191,23 @@ module Workflow
194
191
  end
195
192
 
196
193
  Log.high{"Loading workflow #{wf_name}"}
197
- require_local_workflow(wf_name) or
198
- (Workflow.autoinstall and `rbbt workflow install #{Misc.snake_case(wf_name)} || rbbt workflow install #{wf_name}` and require_local_workflow(wf_name)) or raise("Workflow not found or could not be loaded: #{ wf_name }")
199
- workflow = begin
200
- Misc.string2const Misc.camel_case(wf_name)
201
- rescue
202
- Workflow.workflows.last || true
203
- end
204
- workflow.load_documentation
194
+
195
+ first = nil
196
+ wf_name.split("+").each do |wf_name|
197
+ require_local_workflow(wf_name) or
198
+ (Workflow.autoinstall and `rbbt workflow install #{Misc.snake_case(wf_name)} || rbbt workflow install #{wf_name}` and require_local_workflow(wf_name)) or raise("Workflow not found or could not be loaded: #{ wf_name }")
199
+
200
+ workflow = begin
201
+ Misc.string2const Misc.camel_case(wf_name.split("+").first)
202
+ rescue
203
+ Workflow.workflows.last || true
204
+ end
205
+ workflow.load_documentation
206
+
207
+ first ||= workflow
208
+ end
209
+ return first
210
+
205
211
  workflow
206
212
  end
207
213
 
@@ -22,7 +22,7 @@ Use - to read from STDIN
22
22
  -h--help Print this help
23
23
  -s--sheet* Sheet to extract
24
24
  -skip--skip_rows* Initial rows to skip
25
-
25
+ -o--original Dump the rows without parsing them into TSV
26
26
  EOF
27
27
  if options[:help]
28
28
  if defined? rbbt_usage
@@ -39,5 +39,5 @@ raise ParameterException, "No excel file given" if excelfile.nil?
39
39
 
40
40
  options[:zipped] ||= true if options[:merge]
41
41
  require 'rbbt/tsv/excel'
42
- puts TSV.excel(excelfile, options).to_s
42
+ puts TSV.excel(excelfile, options.merge(:text => options[:original]))
43
43
 
@@ -104,7 +104,7 @@ def fix_options(workflow, task, job_options)
104
104
  elsif input_options[name] and input_options[name][:stream] and value == "-"
105
105
  STDIN
106
106
  else
107
- if Array === value
107
+ if Array === value || IO === value
108
108
  value
109
109
  else
110
110
  array_separator = $array_separator
@@ -137,6 +137,8 @@ def fix_options(workflow, task, job_options)
137
137
  TSV.open(STDIN, :unnamed => true, :sep => $field_separator, :sep2 => ($array_separator || "|"))
138
138
  when (Misc.is_filename?(value) and String)
139
139
  TSV.open(value, :unnamed => true, :sep => $field_separator, :sep2 => ($array_separator || "|"))
140
+ when IO
141
+ TSV.open(value, :unnamed => true, :sep => $field_separator, :sep2 => ($array_separator || "|"))
140
142
  else
141
143
  TSV.open(StringIO.new(value), :unnamed => true, :sep => $field_separator, :sep2 => ($array_separator || "|"))
142
144
  end
@@ -287,8 +289,8 @@ else
287
289
  puts
288
290
  puts $!.message
289
291
  puts
290
-
291
- exit 0
292
+
293
+ exit -1
292
294
  end
293
295
  end
294
296
 
@@ -572,7 +574,9 @@ when Step
572
574
  exit! 0
573
575
  else
574
576
  res.join
575
- out.puts Open.read(res.path) if Open.exist?(res.path) || Open.remote?(res.path) || Open.ssh?(res.path)
577
+ Open.open(res.path, :mode => 'rb') do |io|
578
+ Misc.consume_stream(io, false, out)
579
+ end if Open.exist?(res.path) || Open.remote?(res.path) || Open.ssh?(res.path)
576
580
  end
577
581
  else
578
582
  if Array === res
@@ -2,7 +2,7 @@ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'test_helpe
2
2
  require 'rbbt/tsv/excel'
3
3
 
4
4
  class TestExcel < Test::Unit::TestCase
5
- def _test_xls
5
+ def test_xls
6
6
  content =<<-EOF
7
7
  #Id ValueA ValueB OtherID
8
8
  row1 a|aa|aaa b Id1|Id2
@@ -19,7 +19,7 @@ row2 A B Id3
19
19
  end
20
20
  end
21
21
 
22
- def _test_xlsx
22
+ def test_xlsx
23
23
  content =<<-EOF
24
24
  #Id ValueA ValueB OtherID
25
25
  row1 a|aa|aaa b Id1|Id2
@@ -36,7 +36,7 @@ row2 A B Id3
36
36
  end
37
37
  end
38
38
 
39
- def _test_excel
39
+ def test_excel
40
40
  content =<<-EOF
41
41
  #Id ValueA ValueB OtherID
42
42
  row1 a|aa|aaa b Id1|Id2
@@ -63,7 +63,7 @@ row2 A B Id3
63
63
  end
64
64
  end
65
65
 
66
- def _test_excel_sheets
66
+ def test_excel_sheets
67
67
  content =<<-EOF
68
68
  #Id ValueA ValueB OtherID
69
69
  row1 a|aa|aaa b Id1|Id2
@@ -133,5 +133,39 @@ row2 A B Id3
133
133
  end
134
134
  end
135
135
  end
136
+
137
+ def test_excel_multi_sheets
138
+ content =<<-EOF
139
+ #Id ValueA ValueB OtherID
140
+ row1 a|aa|aaa b Id1|Id2
141
+ row2 A B Id3
142
+ EOF
143
+
144
+ TmpFile.with_file(content) do |filename|
145
+ tsv1 = TSV.open(filename, :sep => /\s+/)
146
+ tsv2 = tsv1.annotate(tsv1.dup)
147
+ tsv3 = tsv1.annotate(tsv1.dup)
148
+
149
+ tsv2["row2"] = [["AA"], ["BB"], ["Id4"]]
150
+ tsv3["row2"] = [["AAA"], ["BBB"], ["Id5"]]
151
+
152
+ TmpFile.with_file(nil, false, :extension => 'xlsx') do |excelfile|
153
+ tsv1.xlsx(excelfile, :sheet => "S1")
154
+ tsv2.xlsx(excelfile, :sheet => "S2", :add_sheet => true)
155
+ workbook = RubyXL::Parser.parse excelfile
156
+
157
+ assert_equal %w(S1 S2), workbook.worksheets.collect{|s| s.sheet_name}
158
+
159
+ new = TSV.excel(excelfile, :sheet => "S1")
160
+ assert_equal %w(row1 row2), new.keys.sort
161
+ assert_equal %w(A), new["row2"]["ValueA"]
162
+
163
+ new = TSV.excel(excelfile, :sheet => "S2")
164
+ assert_equal %w(row1 row2), new.keys.sort
165
+ assert_equal %w(AA), new["row2"]["ValueA"]
166
+
167
+ end
168
+ end
169
+ end
136
170
  end
137
171
 
@@ -203,20 +203,21 @@ class TestWorkflowDependency < Test::Unit::TestCase
203
203
  size = 100000
204
204
  content = (1..size).to_a.collect{|num| "Line #{num}" } * "\n"
205
205
  last_line = nil
206
- Log.severity = 0
207
- TmpFile.with_file(content) do |input_file|
208
- begin
209
- job = DepWorkflow.job(:s3, "TEST", :input_file => input_file)
210
- job.recursive_clean
211
- job.run(:stream)
212
- io = TSV.get_stream job
213
- while line = io.gets
214
- last_line = line.strip
206
+ Log.with_severity 0 do
207
+ TmpFile.with_file(content) do |input_file|
208
+ begin
209
+ job = DepWorkflow.job(:s3, "TEST", :input_file => input_file)
210
+ job.recursive_clean
211
+ job.run(:stream)
212
+ io = TSV.get_stream job
213
+ while line = io.gets
214
+ last_line = line.strip
215
+ end
216
+ io.join if io.respond_to? :join
217
+ rescue Exception
218
+ job.abort
219
+ raise $!
215
220
  end
216
- io.join if io.respond_to? :join
217
- rescue Exception
218
- job.abort
219
- raise $!
220
221
  end
221
222
  end
222
223
  assert last_line.include? "Line #{size}"
@@ -0,0 +1,46 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
2
+ require 'rbbt/workflow/step/save_load_inputs'
3
+
4
+ ENV["RBBT_DEBUG_JOB_HASH"] = true.to_s
5
+ require 'rbbt/workflow'
6
+ module TestSaveLoadWF
7
+ extend Workflow
8
+
9
+ task :number => :integer do
10
+ 10
11
+ end
12
+
13
+ task :list => :array do
14
+ (0..10).to_a.collect{|e| e.to_s}
15
+ end
16
+
17
+ input :list, :array
18
+ input :number, :integer
19
+ task :reverse => :array do |list|
20
+ list.reverse
21
+ end
22
+
23
+ dep :list
24
+ dep :number
25
+ dep :reverse, :list => :list, :number => :number
26
+ task :prefix => :array do
27
+ step(:reverse).run.collect{|e| "A-#{e}" }
28
+ end
29
+ end
30
+
31
+ class TestSaveLoad < Test::Unit::TestCase
32
+ def test_save
33
+ Log.with_severity 0 do
34
+ job = TestSaveLoadWF.job(:prefix)
35
+ job.recursive_clean
36
+ job = TestSaveLoadWF.job(:prefix)
37
+ TmpFile.with_file do |directory|
38
+ Step.save_job_inputs(job.step(:reverse), directory)
39
+ job.produce
40
+ newjob = TestSaveLoadWF.job_for_directory_inputs(:reverse, directory)
41
+ assert_equal job.rec_dependencies.last.path, newjob.path
42
+ end
43
+ end
44
+ end
45
+ end
46
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbbt-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.32.23
4
+ version: 5.32.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
11
+ date: 2021-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -172,6 +172,7 @@ executables:
172
172
  - rbbt_Rutil.rb
173
173
  - rbbt
174
174
  - rbbt_dangling_locks.rb
175
+ - rbbt_find.rb
175
176
  extensions: []
176
177
  extra_rdoc_files:
177
178
  - LICENSE
@@ -183,6 +184,7 @@ files:
183
184
  - bin/rbbt_Rutil.rb
184
185
  - bin/rbbt_dangling_locks.rb
185
186
  - bin/rbbt_exec.rb
187
+ - bin/rbbt_find.rb
186
188
  - bin/rbbt_query.rb
187
189
  - etc/app.d/base.rb
188
190
  - etc/app.d/entities.rb
@@ -343,6 +345,7 @@ files:
343
345
  - lib/rbbt/workflow/step/info.rb
344
346
  - lib/rbbt/workflow/step/prepare.rb
345
347
  - lib/rbbt/workflow/step/run.rb
348
+ - lib/rbbt/workflow/step/save_load_inputs.rb
346
349
  - lib/rbbt/workflow/step/status.rb
347
350
  - lib/rbbt/workflow/task.rb
348
351
  - lib/rbbt/workflow/usage.rb
@@ -548,6 +551,7 @@ files:
548
551
  - test/rbbt/util/test_simpleopt.rb
549
552
  - test/rbbt/util/test_tmpfile.rb
550
553
  - test/rbbt/workflow/step/test_dependencies.rb
554
+ - test/rbbt/workflow/step/test_save_load_inputs.rb
551
555
  - test/rbbt/workflow/test_doc.rb
552
556
  - test/rbbt/workflow/test_remote_workflow.rb
553
557
  - test/rbbt/workflow/test_schedule.rb
@@ -590,6 +594,7 @@ test_files:
590
594
  - test/rbbt/workflow/test_schedule.rb
591
595
  - test/rbbt/workflow/test_step.rb
592
596
  - test/rbbt/workflow/step/test_dependencies.rb
597
+ - test/rbbt/workflow/step/test_save_load_inputs.rb
593
598
  - test/rbbt/workflow/test_task.rb
594
599
  - test/rbbt/resource/test_path.rb
595
600
  - test/rbbt/util/test_colorize.rb