rbbt-util 5.33.8 → 5.33.12

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