rbbt-util 5.33.8 → 5.33.12

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: aaa014ffdad4e098212cc3f7cefc4d04ac62a7f7fcbf17bbbab9415c6253d9ef
4
- data.tar.gz: b8a2a233686ec2f229ed79bb19d87d8eb79ad945142305f7b61dcdb11f5f7912
3
+ metadata.gz: 729b93bb0b82b05a03eb9cdf99728b4793ecd002ab06a92c08dc899341d26810
4
+ data.tar.gz: 568b263ae5bbc16e18383bd0fc5fb42054d2954b674bb1df97f80280ade9e7b2
5
5
  SHA512:
6
- metadata.gz: 564242bef1dd92c2f53a5fe6c967624de26d7ae7eeb4da1ef2a1f682db9cf6d4b0bf0f8e76b3a600afe6af7bb443df28a8fe50e570c3c56265319eb607d6c1fc
7
- data.tar.gz: ac7c01fa7e8fccdff8dfc861b82f28889a68f77886c198ff55b09558b36857ec9c29a8bae979bc7d088f311ad81515676bc7a4cc30097fd6c4b7586e6838c0e3
6
+ metadata.gz: 1c56e3f171523bb412b391899b93ba88d80038a2a201ed4573897c3039526fbf1f05d2a2bcb81b837d6cb9ad31672c7c5a67572d7baa3789c10f3fc3929db274
7
+ data.tar.gz: b178ecce6c10f7933bdafd3cf495e3a185d6f0005b5111ed6b86f79f70b9608d613c837d7141c6ca42bf4504d352f46102d2ac628bc19d6e9a2001dbcc081284
@@ -88,8 +88,8 @@ module HPC
88
88
  def rbbt_job_exec_cmd(job, options)
89
89
 
90
90
  jobname = job.clean_name
91
- workflow = job.workflow
92
- task = job.task_name
91
+ workflow = job.original_workflow || job.workflow
92
+ task = job.original_task_name || job.task_name
93
93
 
94
94
  Misc.add_defaults options, :jobname => jobname
95
95
 
@@ -535,8 +535,8 @@ env > #{batch_options[:fenv]}
535
535
  :batch_base_dir, :clean_batch_job, :remove_batch_dir, :batch_procpath, :tail, :batch_dependencies, :dry_run,
536
536
  :batch_base_dir => File.expand_path(File.join('~/rbbt-batch'))
537
537
 
538
- workflow = job.workflow
539
- task_name = job.task_name
538
+ workflow = job.original_workflow ||job.workflow
539
+ task_name = job.original_task_name || job.task_name
540
540
 
541
541
  workflows_to_load = job.rec_dependencies.select{|d| Step === d}.collect{|d| d.workflow }.compact.collect(&:to_s) - [workflow.to_s]
542
542
 
@@ -101,7 +101,9 @@ module HPC
101
101
 
102
102
  batches.each do |batch|
103
103
  job_rules = batch[:jobs].inject(nil) do |acc,job|
104
- task_rules = task_specific_rules(rules, job.workflow, job.task_name)
104
+ workflow = job.original_workflow || job.workflow
105
+ task_name = job.original_task_name || job.task_name
106
+ task_rules = task_specific_rules(rules, workflow, task_name)
105
107
  acc = accumulate_rules(acc, task_rules.dup)
106
108
  end
107
109
 
@@ -120,13 +122,16 @@ module HPC
120
122
  end
121
123
 
122
124
  batches.each do |batch|
125
+ next if batch[:top_level].overriden?
123
126
  next unless batch[:rules][:skip]
124
127
  batch[:rules].delete :skip
125
128
  next if batch[:deps].nil?
126
129
 
127
130
  if batch[:deps].any?
131
+ batch_dep_jobs = batch[:top_level].rec_dependencies
128
132
  target = batch[:deps].select do |target|
129
- (batch[:deps] - [target] - target[:deps]).empty?
133
+ batch_dep_jobs.include?(target[:top_level]) && # Don't piggyback batches that are an input dependency, only real dependencies
134
+ (batch[:deps] - [target] - target[:deps]).empty?
130
135
  end.first
131
136
  next if target.nil?
132
137
  target[:jobs] = batch[:jobs] + target[:jobs]
@@ -4,8 +4,10 @@ module HPC
4
4
  return [] if Symbol === job.overriden
5
5
  matches = []
6
6
  chains.each do |name, chain|
7
- next unless chain[:tasks].include?(job.workflow.to_s)
8
- next unless chain[:tasks][job.workflow.to_s].include?(job.task_name.to_s)
7
+ workflow = job.original_workflow || job.workflow
8
+ task_name = job.original_task_name || job.task_name
9
+ next unless chain[:tasks].include?(workflow.to_s)
10
+ next unless chain[:tasks][workflow.to_s].include?(task_name.to_s)
9
11
  matches << name
10
12
  end
11
13
  matches
@@ -38,46 +40,50 @@ module HPC
38
40
  end
39
41
 
40
42
  def self.job_chains(rules, job)
41
- chains = self.parse_chains(rules)
42
-
43
- matches = check_chains(chains, job)
44
-
45
- dependencies = job_dependencies(job)
46
-
47
- job_chains = []
48
- new_job_chains = {}
49
- dependencies.each do |dep|
50
- dep_matches = check_chains(chains, dep)
51
- common = matches & dep_matches
52
-
53
- dep_chains = job_chains(rules, dep)
54
- found = []
55
- dep_chains.each do |match,info|
56
- if common.include?(match)
57
- found << match
58
- new_info = new_job_chains[match] ||= {}
59
- new_info[:jobs] ||= []
60
- new_info[:jobs].concat info[:jobs]
61
- new_info[:top_level] = job
62
- else
43
+ @@job_chains ||= {}
44
+ @@job_chains[Misc.digest([rules, job.path].inspect)] ||=
45
+ begin
46
+ chains = self.parse_chains(rules)
47
+
48
+ matches = check_chains(chains, job)
49
+
50
+ dependencies = job_dependencies(job)
51
+
52
+ job_chains = []
53
+ new_job_chains = {}
54
+ dependencies.each do |dep|
55
+ dep_matches = check_chains(chains, dep)
56
+ common = matches & dep_matches
57
+
58
+ dep_chains = job_chains(rules, dep)
59
+ found = []
60
+ dep_chains.each do |match,info|
61
+ if common.include?(match)
62
+ found << match
63
+ new_info = new_job_chains[match] ||= {}
64
+ new_info[:jobs] ||= []
65
+ new_info[:jobs].concat info[:jobs]
66
+ new_info[:top_level] = job
67
+ else
68
+ job_chains << [match, info]
69
+ end
70
+ end
71
+
72
+ (common - found).each do |match|
73
+ info = {}
74
+ info[:jobs] = [job, dep]
75
+ info[:top_level] = job
76
+ job_chains << [match, info]
77
+ end
78
+ end
79
+
80
+ new_job_chains.each do |match,info|
81
+ info[:jobs].prepend job
63
82
  job_chains << [match, info]
64
83
  end
65
- end
66
84
 
67
- (common - found).each do |match|
68
- info = {}
69
- info[:jobs] = [job, dep]
70
- info[:top_level] = job
71
- job_chains << [match, info]
85
+ job_chains
72
86
  end
73
- end
74
-
75
- new_job_chains.each do |match,info|
76
- info[:jobs].prepend job
77
- job_chains << [match, info]
78
- end
79
-
80
- job_chains
81
87
  end
82
88
 
83
89
  end
@@ -30,6 +30,7 @@ module HPC
30
30
  options.delete "printpath"
31
31
  options.delete "detach"
32
32
  options.delete "jobname"
33
+ options.delete "load_inputs"
33
34
 
34
35
  Log.high "Prepare for exec"
35
36
  prepare_for_execution(job)
@@ -81,7 +82,7 @@ module HPC
81
82
 
82
83
  if options[:dry_run]
83
84
  puts Log.color(:magenta, "Manifest: ") + Log.color(:blue, job_options[:manifest] * ", ") + " - tasks: #{job_options[:task_cpus] || 1} - time: #{job_options[:time]} - config: #{job_options[:config_keys]}"
84
- puts Log.color(:magenta, "Deps: ") + Log.color(:blue, job_options[:batch_dependencies]*", ")
85
+ puts Log.color(:yellow, "Deps: ") + Log.color(:blue, job_options[:batch_dependencies]*", ")
85
86
  puts Log.color(:yellow, "Path: ") + top[:top_level].path
86
87
  puts Log.color(:yellow, "Options: ") + job_options.inspect
87
88
  batch_ids[top] = top[:top_level].task_signature
@@ -94,8 +94,8 @@ export BATCH_SYSTEM=SLURM
94
94
 
95
95
  return if Open.exists?(fexit)
96
96
 
97
- STDERR.puts Log.color(:magenta, "Issuing SLURM file: #{fcmd}")
98
- STDERR.puts Open.read(fcmd)
97
+ Log.info "Issuing SLURM file: #{fcmd}"
98
+ Log.debug Open.read(fcmd)
99
99
 
100
100
  if File.exists?(fjob)
101
101
  job = Open.read(fjob).to_i
@@ -0,0 +1,79 @@
1
+ module Misc
2
+ PUSHBULLET_KEY=begin
3
+ if ENV["PUSHBULLET_KEY"]
4
+ ENV["PUSHBULLET_KEY"]
5
+ else
6
+ config_api = File.join(ENV['HOME'], 'config/apps/pushbullet/apikey')
7
+ if File.exist? config_api
8
+ File.read(config_api).strip
9
+ else
10
+ nil
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.notify(description, event='notification', key = nil)
16
+ if PUSHBULLET_KEY.nil? and key.nil?
17
+ Log.warn "Could not notify, no PUSHBULLET_KEY"
18
+ return
19
+ end
20
+
21
+ Thread.new do
22
+ application = 'rbbt'
23
+ event ||= 'notification'
24
+ key ||= PUSHBULLET_KEY
25
+ `curl -s --header "Authorization: Bearer #{key}" -X POST https://api.pushbullet.com/v2/pushes --header 'Content-Type: application/json' --data-binary '{"type": "note", "title": "#{event}", "body": "#{description}"}'`
26
+ end
27
+ end
28
+
29
+ def self.send_email_old(from, to, subject, message, options = {})
30
+ IndiferentHash.setup(options)
31
+ options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login
32
+
33
+ server, port, user, pass, from_alias, to_alias, auth = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth
34
+
35
+ msg = <<-END_OF_MESSAGE
36
+ From: #{from_alias} <#{from}>
37
+ To: #{to_alias} <#{to}>
38
+ Subject: #{subject}
39
+
40
+ #{message}
41
+ END_OF_MESSAGE
42
+
43
+ Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
44
+ smtp.send_message msg, from, to
45
+ end
46
+ end
47
+
48
+ def self.send_email(from, to, subject, message, options = {})
49
+ require 'mail'
50
+
51
+ IndiferentHash.setup(options)
52
+ options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login, :files => []
53
+
54
+ server, port, user, pass, from_alias, to_alias, auth, files = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth, :files
55
+
56
+ files = [] if files.nil?
57
+ files = [files] unless Array === files
58
+
59
+ Mail.defaults do
60
+ delivery_method :smtp, address: server, port: port, user_name: user, password: pass
61
+ end
62
+
63
+ mail = Mail.deliver do
64
+ from "#{from_alias} <#{from}>"
65
+ to "#{to_alias} <#{to}>"
66
+ subject subject
67
+
68
+ text_part do
69
+ body message
70
+ end
71
+
72
+ files.each do |file|
73
+ file = file.find if Path === file
74
+ file = file.path if Step === file
75
+ end
76
+ end
77
+ end
78
+
79
+ end
@@ -385,32 +385,6 @@ def self.add_libdir(dir=nil)
385
385
  `ps -o rss -p #{pid || $$}`.strip.split.last.to_i
386
386
  end
387
387
 
388
- PUSHBULLET_KEY=begin
389
- if ENV["PUSHBULLET_KEY"]
390
- ENV["PUSHBULLET_KEY"]
391
- else
392
- config_api = File.join(ENV['HOME'], 'config/apps/pushbullet/apikey')
393
- if File.exist? config_api
394
- File.read(config_api).strip
395
- else
396
- nil
397
- end
398
- end
399
- end
400
-
401
- def self.notify(description, event='notification', key = nil)
402
- if PUSHBULLET_KEY.nil? and key.nil?
403
- Log.warn "Could not notify, no PUSHBULLET_KEY"
404
- return
405
- end
406
-
407
- Thread.new do
408
- application = 'rbbt'
409
- event ||= 'notification'
410
- key ||= PUSHBULLET_KEY
411
- `curl -s --header "Authorization: Bearer #{key}" -X POST https://api.pushbullet.com/v2/pushes --header 'Content-Type: application/json' --data-binary '{"type": "note", "title": "#{event}", "body": "#{description}"}'`
412
- end
413
- end
414
388
 
415
389
  def self.unzip_in_dir(file, dir)
416
390
  raise "Target is not a directory: #{file}" if File.exist?(dir) and not File.directory?(dir)
@@ -355,7 +355,7 @@ module Misc
355
355
  "<IO:" << obj.path << "--" << mtime_str(obj.path) << ">"
356
356
  end
357
357
  when (defined? Step and Step)
358
- "<IO:" << obj.short_path << ">"
358
+ "<IO:" << obj.short_path_real << ">"
359
359
  when IO
360
360
  if obj.respond_to? :filename and obj.filename
361
361
  if defined?(Step) && Open.exists?(Step.info_file(obj.filename))
@@ -16,25 +16,6 @@ module Misc
16
16
  end
17
17
  end
18
18
 
19
- def self.send_email(from, to, subject, message, options = {})
20
- IndiferentHash.setup(options)
21
- options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login
22
-
23
- server, port, user, pass, from_alias, to_alias, auth = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth
24
-
25
- msg = <<-END_OF_MESSAGE
26
- From: #{from_alias} <#{from}>
27
- To: #{to_alias} <#{to}>
28
- Subject: #{subject}
29
-
30
- #{message}
31
- END_OF_MESSAGE
32
-
33
- Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
34
- smtp.send_message msg, from, to
35
- end
36
- end
37
-
38
19
  def self.env_add(var, value, sep = ":", prepend = true)
39
20
  ENV[var] ||= ""
40
21
  return if ENV[var] =~ /(#{sep}|^)#{Regexp.quote value}(#{sep}|$)/
@@ -113,9 +94,10 @@ end
113
94
  end
114
95
 
115
96
  def self.is_filename?(string, need_to_exists = true)
97
+ return false if string.nil?
116
98
  return true if defined? Path and Path === string
117
99
  return true if string.respond_to? :exists
118
- return true if String === string and string.length < 265 and (File.exist?(string) || ! need_to_exists)
100
+ return true if String === string and string.split("/").select{|p| p.length > 265}.empty? and (! need_to_exists || File.exist?(string))
119
101
  return false
120
102
  end
121
103
 
@@ -20,6 +20,7 @@ require 'rbbt/util/misc/options'
20
20
  require 'rbbt/util/misc/system'
21
21
  require 'rbbt/util/misc/objects'
22
22
  require 'rbbt/util/misc/manipulation'
23
+ require 'rbbt/util/misc/communication'
23
24
 
24
25
  require 'to_regexp'
25
26
 
@@ -678,7 +678,14 @@ module Open
678
678
  if Open.exists? notification_file
679
679
  key = Open.read(notification_file).strip
680
680
  key = nil if key.empty?
681
- Misc.notify("Wrote " << file, nil, key)
681
+ if key.include?("@")
682
+ to = from = key
683
+ subject = "Wrote " << file
684
+ message = "Content attached"
685
+ Misc.send_email(from, to, subject, message, :files => [file])
686
+ else
687
+ Misc.notify("Wrote " << file, nil, key)
688
+ end
682
689
  Open.rm notification_file
683
690
  end
684
691
  rescue
@@ -72,9 +72,12 @@ module Workflow
72
72
  def setup_override_dependency(dep, workflow, task_name)
73
73
  return [] if dep == :skip || dep == 'skip'
74
74
  dep = Step === dep ? dep.dup : Workflow.load_step(dep)
75
+
76
+ dep.original_workflow ||= dep.workflow if dep.workflow
77
+ dep.original_task_name ||= dep.task_name if dep.workflow
78
+
75
79
  dep.workflow = workflow
76
80
  dep.info[:name] = dep.name
77
- dep.original_task_name ||= dep.task_name if dep.workflow
78
81
 
79
82
 
80
83
  begin
@@ -96,6 +96,10 @@ class Step
96
96
  [task_name, name] * "/"
97
97
  end
98
98
 
99
+ def short_path_real
100
+ [(Symbol === overriden ? overriden : task_name).to_s, name] * "/"
101
+ end
102
+
99
103
  def workflow_short_path
100
104
  return short_path unless workflow
101
105
  workflow.to_s + "#" + short_path
@@ -510,7 +510,7 @@ class Step
510
510
 
511
511
  def overriden?
512
512
  return true if @overriden
513
- return true if dependencies.select{|dep| dep.overriden? }.any?
513
+ return true if dependencies && dependencies.select{|dep| dep.overriden? }.any?
514
514
  info[:archived_info].each do |f,i|
515
515
  next if Symbol === i
516
516
  return true if i[:overriden] || i["overriden"]
@@ -1,4 +1,5 @@
1
1
  module Workflow
2
+
2
3
  def self.load_inputs(dir, input_names, input_types)
3
4
  inputs = {}
4
5
  if File.exists?(dir) && ! File.directory?(dir)
@@ -20,21 +21,59 @@ module Workflow
20
21
  Log.debug "Trying #{ input }: #{file}"
21
22
  next unless file and (File.symlink?(file) || file.exists?)
22
23
 
23
- type = input_types[input]
24
+ type = orig_type = input_types[input]
24
25
 
25
26
  type = :io if file.split(".").last == 'as_io'
26
27
 
28
+ type = :io_array if file.split(".").last == 'as_io_array'
29
+
30
+ type = :step if file.split(".").last == 'as_step'
31
+
32
+ type = :step_array if file.split(".").last == 'as_step_array'
33
+
34
+ type = :step_file if file.split(".").last == 'as_step_file'
35
+
36
+ type = :step_file_array if file.split(".").last == 'as_step_file_array'
37
+
27
38
  type = :path if file.split(".").last == 'as_path'
28
39
 
40
+ type = :path_array if file.split(".").last == 'as_path_array'
41
+
42
+ type = :filename if file.split(".").last == 'as_filename'
43
+
29
44
  type = :nofile if file.split(".").last == 'nofile'
30
45
 
31
46
  case type
32
47
  when :nofile
33
48
  inputs[input.to_sym] = Open.realpath(file)
49
+ when :path_array
50
+ inputs[input.to_sym] = Open.read(file).strip.split("\n")
34
51
  when :path
35
- inputs[input.to_sym] = Open.realpath(Open.read(file).strip)
52
+ inputs[input.to_sym] = Open.read(file).strip.split("\n").first
53
+ when :io
54
+ inputs[input.to_sym] = Open.open(Open.realpath(file)).split("\n")
36
55
  when :io
37
- inputs[input.to_sym] = Open.open(Open.realpath(file))
56
+ inputs[input.to_sym] = Open.realpath(file).split("\n").collect{|f| Open.open(f)}
57
+ when :step_array
58
+ steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
59
+ inputs[input.to_sym] = steps
60
+ when :step
61
+ steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
62
+ inputs[input.to_sym] = steps.first
63
+ when :step_file
64
+ path = Open.read(file).strip
65
+ path.extend Path
66
+ step_path = path.match(/(.*)\.files/)[1]
67
+ path.resource = Step.new step_path
68
+ inputs[input.to_sym] = path
69
+ when :step_file_array
70
+ paths = Open.read(file).split("\n")
71
+ paths.each do |path|
72
+ path.extend Path
73
+ step_path = path.match(/(.*)\.files/)[1]
74
+ path.resource = Step.new step_path
75
+ end
76
+ inputs[input.to_sym] = paths
38
77
  when :file, :binary
39
78
  Log.debug "Pointing #{ input } to #{file}"
40
79
  if file =~ /\.yaml/
@@ -87,60 +126,149 @@ module Workflow
87
126
  job(task_name, jobname, inputs)
88
127
  end
89
128
 
129
+ #def self.load_inputs_old(dir, input_names, input_types)
130
+ # inputs = {}
131
+ # if File.exists?(dir) && ! File.directory?(dir)
132
+ # Log.debug "Loading inputs from #{dir}, not a directory trying as tar.gz"
133
+ # tarfile = dir
134
+ # digest = CMD.cmd("md5sum '#{tarfile}'").read.split(" ").first
135
+ # tmpdir = Rbbt.tmp.input_bundle[digest].find
136
+ # Misc.untar(tarfile, tmpdir) unless File.exists? tmpdir
137
+ # files = tmpdir.glob("*")
138
+ # if files.length == 1 && File.directory?(files.first)
139
+ # tmpdir = files.first
140
+ # end
141
+ # load_inputs(tmpdir, input_names, input_types)
142
+ # else
143
+ # dir = Path.setup(dir.dup)
144
+ # input_names.each do |input|
145
+ # file = dir[input].find
146
+ # file = dir.glob(input.to_s + ".*").reject{|f| f =~ /\.md5$/}.first if file.nil? or not (File.symlink?(file) || file.exists?)
147
+ # Log.debug "Trying #{ input }: #{file}"
148
+ # next unless file and (File.symlink?(file) || file.exists?)
149
+
150
+ # type = input_types[input]
151
+
152
+ # type = :io if file.split(".").last == 'as_io'
153
+
154
+ # type = :path if file.split(".").last == 'as_path'
155
+
156
+ # type = :filename if file.split(".").last == 'as_filename'
157
+
158
+ # type = :nofile if file.split(".").last == 'nofile'
159
+
160
+ # case type
161
+ # when :nofile
162
+ # inputs[input.to_sym] = Open.realpath(file)
163
+ # when :path
164
+ # inputs[input.to_sym] = Open.realpath(Open.read(file).strip)
165
+ # when :io
166
+ # inputs[input.to_sym] = Open.open(Open.realpath(file))
167
+ # when :file, :binary
168
+ # Log.debug "Pointing #{ input } to #{file}"
169
+ # if file =~ /\.yaml/
170
+ # inputs[input.to_sym] = YAML.load(Open.read(file))
171
+ # else
172
+ # if File.symlink?(file)
173
+ # link_target = File.expand_path(File.readlink(file), File.dirname(file))
174
+ # inputs[input.to_sym] = link_target
175
+ # else
176
+ # inputs[input.to_sym] = Open.realpath(file)
177
+ # end
178
+ # end
179
+ # when :text
180
+ # Log.debug "Reading #{ input } from #{file}"
181
+ # inputs[input.to_sym] = Open.read(file)
182
+ # when :array
183
+ # Log.debug "Reading array #{ input } from #{file}"
184
+ # inputs[input.to_sym] = Open.read(file).split("\n")
185
+ # when :tsv
186
+ # Log.debug "Opening tsv #{ input } from #{file}"
187
+ # inputs[input.to_sym] = TSV.open(file)
188
+ # when :boolean
189
+ # inputs[input.to_sym] = (file.read.strip == 'true')
190
+ # else
191
+ # Log.debug "Loading #{ input } from #{file}"
192
+ # inputs[input.to_sym] = file.read.strip
193
+ # end
194
+
195
+ # end
196
+ # inputs = IndiferentHash.setup(inputs)
197
+
198
+ # dir.glob("*#*").each do |od|
199
+ # name = File.basename(od)
200
+ # value = Open.read(od)
201
+ # Log.debug "Loading override dependency #{ name } as #{value}"
202
+ # inputs[name] = value.chomp
203
+ # end
204
+
205
+ # inputs
206
+ # end
207
+ #end
90
208
  end
91
209
 
92
210
  class Step
93
- def self.save_inputs(inputs, input_types, input_options, dir)
94
- inputs.each do |name,value|
95
- type = input_types[name]
96
- type = type.to_s if type
97
- path = File.join(dir, name.to_s)
98
-
99
- path = path + '.as_io' if (IO === value || Step === value) && ! (input_options[name] && input_options[name][:nofile])
100
- Log.debug "Saving job input #{name} (#{type}) into #{path}"
101
-
102
- case
103
- when IO === value
104
- Open.write(path, value.to_s)
105
- when Step === value
106
- Open.ln_s(value.path, path)
107
- when type.to_s == "binary"
108
- if String === value && File.exists?(value)
109
- value = File.expand_path(value)
110
- Open.ln_s(value, path)
111
- elsif String === value && Misc.is_filename?(value, false)
112
- Open.write(path + '.as_path' , value)
113
- else
114
- Open.write(path, value, :mode => 'wb')
115
- end
116
- when type.to_s == "file"
117
- if String === value && File.exists?(value)
118
- value = File.expand_path(value)
119
- Open.ln_s(value, path)
211
+ def self.save_input(name, value, type, dir)
212
+ path = File.join(dir, name.to_s)
213
+
214
+ case value
215
+ when Path
216
+ if Step === value.resource
217
+ path = path + '.as_step_file'
218
+ else
219
+ path = path + '.as_path'
220
+ end
221
+ when String
222
+ if Misc.is_filename?(value, false)
223
+ value = value.dup
224
+ value.extend Path
225
+ return save_input(name, value, type, dir)
226
+ end
227
+ when IO
228
+ path = path + '.as_io'
229
+ when Step
230
+ value = value.path
231
+ path = path + '.as_step'
232
+ when Array
233
+ case value.first
234
+ when Path
235
+ if Step === value.first.resource
236
+ path = path + '.as_step_file_array'
120
237
  else
121
- value = value.collect{|v| v = "#{v}" if Path === v; v } if Array === value
122
- value = "#{value}" if Path === value
123
- Open.write(path + '.yaml', value.to_yaml)
238
+ path = path + '.as_path_array'
124
239
  end
125
- when Array === value
126
- Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
127
- when IO === value
128
- if value.filename && String === value.filename && File.exists?(value.filename)
129
- Open.ln_s(value.filename, path)
130
- else
131
- Open.write(path, value)
240
+ when String
241
+ if Misc.is_filename?(value.first, false)
242
+ path = path + '.as_path_array'
132
243
  end
133
- else
134
- Open.write(path, value.to_s)
244
+ when IO
245
+ path = path + '.as_io_array'
246
+ when Step
247
+ path = path + '.as_step_array'
248
+ value = value.collect{|s| s.path }
135
249
  end
250
+
251
+ value = value * "\n"
252
+ end
253
+
254
+ Log.debug "Saving job input #{name} (#{type}) into #{path}"
255
+ Open.write(path, value.to_s)
256
+ end
257
+
258
+ def self.save_inputs(inputs, input_types, input_options, dir)
259
+ inputs.each do |name,value|
260
+ type = input_types[name]
261
+ type = type.to_s if type
262
+
263
+ save_input(name, value, type, dir)
136
264
  end.any?
137
265
  end
138
266
 
139
267
  def self.save_job_inputs(job, dir, options = nil)
140
268
  options = IndiferentHash.setup options.dup if options
141
269
 
142
- task_name = Symbol === job.overriden ? job.overriden : job.task_name
143
- workflow = job.workflow
270
+ task_name = job.original_task_name || job.task_name
271
+ workflow = job.original_workflow || job.workflow
144
272
  workflow = Kernel.const_get workflow if String === workflow
145
273
  if workflow
146
274
  task_info = IndiferentHash.setup(workflow.task_info(task_name))
@@ -176,4 +304,60 @@ class Step
176
304
 
177
305
  inputs.keys
178
306
  end
307
+
308
+ #def self.save_inputs_old(inputs, input_types, input_options, dir)
309
+ # inputs.each do |name,value|
310
+ # type = input_types[name]
311
+ # type = type.to_s if type
312
+ # path = File.join(dir, name.to_s)
313
+
314
+ # if (IO === value || Step === value) && ! (input_options[name] && input_options[name][:nofile])
315
+ # path = path + '.as_io'
316
+ # elsif Misc.is_filename?(value, false)
317
+ # path = path + '.as_filename'
318
+ # end
319
+
320
+ # Log.debug "Saving job input #{name} (#{type}) into #{path}"
321
+
322
+ # case
323
+ # when IO === value
324
+ # Open.write(path, value.to_s)
325
+ # when Step === value
326
+ # Open.ln_s(value.path, path)
327
+ # when type.to_s == "binary"
328
+ # if String === value && File.exists?(value)
329
+ # value = File.expand_path(value)
330
+ # Open.ln_s(value, path)
331
+ # elsif String === value && Misc.is_filename?(value, false)
332
+ # Open.write(path + '.as_path' , value)
333
+ # else
334
+ # Open.write(path, value, :mode => 'wb')
335
+ # end
336
+ # when TSV === value
337
+ # Open.write(path, value.to_s)
338
+ # when Array === value
339
+ # Open.write(path, value.collect{|v| Step === v ? v.path : v.to_s} * "\n")
340
+ # when %w(file tsv array).include?(type.to_s)
341
+ # if String === value && File.exists?(value)
342
+ # value = File.expand_path(value)
343
+ # Open.ln_s(value, path)
344
+ # elsif String === value && Misc.is_filename?(value, false)
345
+ # Open.write(path + '.as_path' , value)
346
+ # else
347
+ # value = value.collect{|v| v = "#{v}" if Path === v; v } if Array === value
348
+ # value = "#{value}" if Path === value
349
+ # Open.write(path + '.yaml', value.to_yaml)
350
+ # end
351
+ # when IO === value
352
+ # if value.filename && String === value.filename && File.exists?(value.filename)
353
+ # Open.ln_s(value.filename, path)
354
+ # else
355
+ # Open.write(path, value)
356
+ # end
357
+ # else
358
+ # Open.write(path, value.to_s)
359
+ # end
360
+ # end.any?
361
+ #end
362
+
179
363
  end
@@ -15,7 +15,7 @@ class Step
15
15
  attr_accessor :exec
16
16
  attr_accessor :relocated
17
17
  attr_accessor :result, :mutex, :seen
18
- attr_accessor :real_inputs, :original_task_name
18
+ attr_accessor :real_inputs, :original_task_name, :original_workflow
19
19
 
20
20
  RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
21
21
 
@@ -376,9 +376,9 @@ class Step
376
376
  }
377
377
  raise "Dependency step not found: #{ name }" if deps.empty?
378
378
  if (deps & self.dependencies).any?
379
- (deps & self.dependencies).first
379
+ (deps & self.dependencies).last
380
380
  else
381
- deps.first
381
+ deps.last
382
382
  end
383
383
  end
384
384
  end
@@ -141,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
141
141
  rescue
142
142
  nodes = []
143
143
  end
144
- elsif job_nodes[id]
144
+ elsif job_nodes && job_nodes[id]
145
145
  nodes = job_nodes[id].reject{|n| n.include? "("}
146
146
  else
147
147
  nodes = []
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
209
209
  if j.file(:progress).exists?
210
210
  bar = Log::ProgressBar.new
211
211
  bar.load(j.file(:progress).yaml)
212
- prog_rep << bar.report_msg.split("·")[0..1]
212
+ rep = bar.report_msg.split("·")[1]
213
+ rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
214
+ prog_rep << [rep]
213
215
  end
214
216
  end
215
217
  end
@@ -340,7 +342,10 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
340
342
  has_bar = true
341
343
  end
342
344
  end
343
- puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step.status}" unless has_bar
345
+ step_status = step.status
346
+ step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
347
+ step_status = Log.color :green, step_status if step_status.to_s == 'done'
348
+ puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
344
349
  end
345
350
  end
346
351
 
@@ -60,5 +60,6 @@ class Step
60
60
  end
61
61
  end
62
62
 
63
- ARGV.concat ["-W", $slurm_options[:workflows], '--detach'] if $slurm_options[:workflows]
63
+ ARGV.concat ['--detach']
64
+ ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
64
65
  load Rbbt.share.rbbt_commands.workflow.task.find
@@ -57,6 +57,7 @@ else
57
57
  step_path = nil
58
58
  end
59
59
 
60
+ puts Log.color(:magenta, "Directory: ") + directory if directory
60
61
  puts Log.color(:magenta, "Step path: ") + step_path if step_path
61
62
 
62
63
  HPC::BATCH_MODULE.follow_job directory, true
@@ -141,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
141
141
  rescue
142
142
  nodes = []
143
143
  end
144
- elsif job_nodes[id]
144
+ elsif job_nodes && job_nodes[id]
145
145
  nodes = job_nodes[id].reject{|n| n.include? "("}
146
146
  else
147
147
  nodes = []
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
209
209
  if j.file(:progress).exists?
210
210
  bar = Log::ProgressBar.new
211
211
  bar.load(j.file(:progress).yaml)
212
- prog_rep << bar.report_msg.split("·")[0..1]
212
+ rep = bar.report_msg.split("·")[1]
213
+ rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
214
+ prog_rep << [rep]
213
215
  end
214
216
  end
215
217
  end
@@ -340,7 +342,10 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
340
342
  has_bar = true
341
343
  end
342
344
  end
343
- puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step.status}" unless has_bar
345
+ step_status = step.status
346
+ step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
347
+ step_status = Log.color :green, step_status if step_status.to_s == 'done'
348
+ puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
344
349
  end
345
350
  end
346
351
 
@@ -60,5 +60,6 @@ class Step
60
60
  end
61
61
  end
62
62
 
63
- ARGV.concat ["-W", $slurm_options[:workflows], '--detach'] if $slurm_options[:workflows]
63
+ ARGV.concat ['--detach']
64
+ ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
64
65
  load Rbbt.share.rbbt_commands.workflow.task.find
@@ -57,6 +57,7 @@ else
57
57
  step_path = nil
58
58
  end
59
59
 
60
+ puts Log.color(:magenta, "Directory: ") + directory if directory
60
61
  puts Log.color(:magenta, "Step path: ") + step_path if step_path
61
62
 
62
63
  HPC::BATCH_MODULE.follow_job directory, true
@@ -141,7 +141,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
141
141
  rescue
142
142
  nodes = []
143
143
  end
144
- elsif job_nodes[id]
144
+ elsif job_nodes && job_nodes[id]
145
145
  nodes = job_nodes[id].reject{|n| n.include? "("}
146
146
  else
147
147
  nodes = []
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
209
209
  if j.file(:progress).exists?
210
210
  bar = Log::ProgressBar.new
211
211
  bar.load(j.file(:progress).yaml)
212
- prog_rep << bar.report_msg.split("·")[0..1]
212
+ rep = bar.report_msg.split("·")[1]
213
+ rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
214
+ prog_rep << [rep]
213
215
  end
214
216
  end
215
217
  end
@@ -340,7 +342,10 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
340
342
  has_bar = true
341
343
  end
342
344
  end
343
- puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step.status}" unless has_bar
345
+ step_status = step.status
346
+ step_status = Log.color :red, step_status if step_status.to_s == 'cleaned'
347
+ step_status = Log.color :green, step_status if step_status.to_s == 'done'
348
+ puts Log.color(:magenta, "Progress: ") + Log.color(:yellow, step.task_signature) + " #{step_status}" unless has_bar
344
349
  end
345
350
  end
346
351
 
@@ -60,5 +60,6 @@ class Step
60
60
  end
61
61
  end
62
62
 
63
- ARGV.concat ["-W", $slurm_options[:workflows], '--detach'] if $slurm_options[:workflows]
63
+ ARGV.concat ['--detach']
64
+ ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
64
65
  load Rbbt.share.rbbt_commands.workflow.task.find
@@ -57,6 +57,7 @@ else
57
57
  step_path = nil
58
58
  end
59
59
 
60
+ puts Log.color(:magenta, "Directory: ") + directory if directory
60
61
  puts Log.color(:magenta, "Step path: ") + step_path if step_path
61
62
 
62
63
  HPC::BATCH_MODULE.follow_job directory, true
@@ -76,6 +76,16 @@ def fix_options(workflow, task, job_options)
76
76
  type = input_types[name]
77
77
  type = type.to_sym if type
78
78
 
79
+ if Step === value
80
+ job_options_cleaned[name] = value
81
+ next
82
+ end
83
+
84
+ if Path === value && Step === value.resource
85
+ job_options_cleaned[name] = value
86
+ next
87
+ end
88
+
79
89
  value = case type
80
90
  when nil
81
91
  value
@@ -148,6 +158,7 @@ def fix_options(workflow, task, job_options)
148
158
  else
149
159
  value
150
160
  end
161
+
151
162
  job_options_cleaned[name] = value
152
163
  end
153
164
 
@@ -0,0 +1,11 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
2
+ require 'rbbt/util/misc/communication'
3
+
4
+ class TestCommunication < Test::Unit::TestCase
5
+ def test_send_email
6
+ to = from = 'mvazque2@localhost'
7
+ subject = message = "Test"
8
+ iii Misc.send_email(to, from, subject, message)
9
+ end
10
+ end
11
+
@@ -26,11 +26,26 @@ module TestSaveLoadWF
26
26
  task :prefix => :array do
27
27
  step(:reverse).run.collect{|e| "A-#{e}" }
28
28
  end
29
+
30
+ input :integer, :integer
31
+ input :float, :float
32
+ input :file, :file
33
+ input :file_no_file, :file, "", nil, :nofile => true
34
+ input :string, :string
35
+ input :select, :select
36
+ input :array, :array
37
+ input :array_no_file, :array, "", nil, :nofile => true
38
+ input :tsv, :tsv, "", nil, :nofile => true
39
+ input :tsv_no_file, :tsv, "", nil, :nofile => true
40
+ input :binary, :binary, "", nil, :nofile => true
41
+ input :binary_no_file, :tsv, "", nil, :nofile => true
42
+ task :save_test => :string do
43
+ "DONE"
44
+ end
29
45
  end
30
46
 
31
47
  class TestSaveLoad < Test::Unit::TestCase
32
48
  def test_save
33
- Log.with_severity 0 do
34
49
  job = TestSaveLoadWF.job(:prefix)
35
50
  job.recursive_clean
36
51
  job = TestSaveLoadWF.job(:prefix)
@@ -40,6 +55,81 @@ class TestSaveLoad < Test::Unit::TestCase
40
55
  newjob = TestSaveLoadWF.job_for_directory_inputs(:reverse, directory)
41
56
  assert_equal job.rec_dependencies.last.path, newjob.path
42
57
  end
58
+ end
59
+
60
+ def test_save_all_normal
61
+ tsv = TSV.setup({}, "Key~Value#:type=:single")
62
+ tsv["key"] = "value"
63
+ options = {
64
+ :float => 0.5,
65
+ :integer => 15,
66
+ :string => "STRING",
67
+ :select => "option",
68
+ :array => [0,1,2,3],
69
+ :tsv => tsv,
70
+ }
71
+ Log.with_severity 0 do
72
+ Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
73
+ job = TestSaveLoadWF.job(:save_test, nil, options)
74
+ TmpFile.with_file do |directory|
75
+ Step.save_job_inputs(job, directory)
76
+ newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
77
+ assert_equal job.path, newjob.path
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def test_save_all_file
84
+ tsv = TSV.setup({}, "Key~Value#:type=:single")
85
+ tsv["key"] = "value"
86
+ Log.with_severity 0 do
87
+ Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
88
+ TmpFile.with_file do |input_file|
89
+ Path.setup(input_file)
90
+ options = {
91
+ :float => input_file.float,
92
+ :integer => input_file.integer,
93
+ :string => input_file.string,
94
+ :select => input_file.select,
95
+ :array => input_file.array,
96
+ :tsv => input_file.tsv_file,
97
+ }
98
+ job = TestSaveLoadWF.job(:save_test, nil, options)
99
+ TmpFile.with_file do |directory|
100
+ Step.save_job_inputs(job, directory)
101
+ newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
102
+ assert_equal job.path, newjob.path
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_save_all_job_file
110
+ tsv = TSV.setup({}, "Key~Value#:type=:single")
111
+ tsv["key"] = "value"
112
+ Log.with_severity 0 do
113
+ Misc.with_env "RBBT_DEBUG_JOB_HASH", "true" do
114
+ TmpFile.with_file do |input_file|
115
+ Path.setup(input_file)
116
+ options = {
117
+ :float => input_file.float,
118
+ :integer => input_file.integer,
119
+ :string => input_file.string,
120
+ :select => input_file.select,
121
+ :array => TestSaveLoadWF.job(:list),
122
+ :binary => TestSaveLoadWF.job(:list).file('binary'),
123
+ :tsv => input_file.tsv_file,
124
+ }
125
+ job = TestSaveLoadWF.job(:save_test, nil, options)
126
+ TmpFile.with_file do |directory|
127
+ Step.save_job_inputs(job, directory)
128
+ newjob = TestSaveLoadWF.job_for_directory_inputs(:save_test, directory)
129
+ assert_equal job.path, newjob.path
130
+ end
131
+ end
132
+ end
43
133
  end
44
134
  end
45
135
  end
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.33.8
4
+ version: 5.33.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-14 00:00:00.000000000 Z
11
+ date: 2022-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -292,6 +292,7 @@ files:
292
292
  - lib/rbbt/util/misc.rb
293
293
  - lib/rbbt/util/misc/annotated_module.rb
294
294
  - lib/rbbt/util/misc/bgzf.rb
295
+ - lib/rbbt/util/misc/communication.rb
295
296
  - lib/rbbt/util/misc/concurrent_stream.rb
296
297
  - lib/rbbt/util/misc/development.rb
297
298
  - lib/rbbt/util/misc/exceptions.rb
@@ -531,6 +532,7 @@ files:
531
532
  - test/rbbt/util/concurrency/test_threads.rb
532
533
  - test/rbbt/util/log/test_progress.rb
533
534
  - test/rbbt/util/misc/test_bgzf.rb
535
+ - test/rbbt/util/misc/test_communication.rb
534
536
  - test/rbbt/util/misc/test_development.rb
535
537
  - test/rbbt/util/misc/test_format.rb
536
538
  - test/rbbt/util/misc/test_lock.rb
@@ -611,6 +613,7 @@ test_files:
611
613
  - test/rbbt/util/misc/test_omics.rb
612
614
  - test/rbbt/util/misc/test_pipes.rb
613
615
  - test/rbbt/util/misc/test_format.rb
616
+ - test/rbbt/util/misc/test_communication.rb
614
617
  - test/rbbt/util/misc/test_lock.rb
615
618
  - test/rbbt/util/misc/test_multipart_payload.rb
616
619
  - test/rbbt/util/misc/test_bgzf.rb