rbbt-util 5.32.23 → 5.32.27

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.
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