rbbt-util 5.38.0 → 5.38.1

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: df9e238ba28f6bc0e16d1a22d8c9c34f7b57334f795ad9c4104ee1e689bc8fd5
4
- data.tar.gz: 61cc2c91be510161edde982567750f13abb2388cf624e15ca1e4c72633382a3b
3
+ metadata.gz: 1121593dec25c29d7986047727d555ed0e75df6b158f9f1332764ad4886462c5
4
+ data.tar.gz: c8e39ef65e23445cf5d0c8817af961a9206016c5e3665d87e042f0fadec2b8df
5
5
  SHA512:
6
- metadata.gz: a3528b56bfc0faebf62c701fcc637a43af8ffe0639a795859f56dca57749b60a3cd821941b7e7bf079cca27a9a8aa8d9d69f71235b41c1ff48e73b4292a31683
7
- data.tar.gz: dd71f1e7b233fb46d5e1210466bd6f64b0dd9162633d475f7e38bc8a057c853411bf27c35ffb3ce935f10b6e8d0055efdd7f5822adf09ff8f95a0bfa0efe8971
6
+ metadata.gz: 22c87766544a52c9c6f0d6da369422a452f553d1a61b82a54674f676a3867a6c1d29028c2efd031563f982cdadbce56d36950c8e100bd34ac2a7e95b39af8a58
7
+ data.tar.gz: 0a79edc89dad388bca9b94dfeccba1df64c4294e84c4f19743608038e55f8800181911d787980adae3ec1c715a993430ccbf2bc07d6212485b89843ada93de74
@@ -154,6 +154,8 @@ module Annotated
154
154
 
155
155
  def self.purge(object)
156
156
  case object
157
+ when Path
158
+ object
157
159
  when String
158
160
  object.respond_to?(:clean_annotations) ?
159
161
  object.clean_annotations :
data/lib/rbbt/persist.rb CHANGED
@@ -115,7 +115,7 @@ module Persist
115
115
  begin
116
116
  case (type || :marshal).to_sym
117
117
  when :path
118
- path
118
+ Path.setup(Open.read(path).strip)
119
119
  when :nil
120
120
  nil
121
121
  when :boolean
@@ -172,7 +172,7 @@ module Persist
172
172
 
173
173
  case (type || :marshal).to_sym
174
174
  when :path
175
- nil
175
+ Open.write(path, content)
176
176
  when :nil
177
177
  nil
178
178
  when :boolean
data/lib/rbbt/resource.rb CHANGED
@@ -350,6 +350,7 @@ url='#{url}'
350
350
  end
351
351
 
352
352
  def identify(path)
353
+ return path unless path.start_with?("/")
353
354
  path = File.expand_path(path)
354
355
  path += "/" if File.directory?(path)
355
356
  resource ||= Rbbt
@@ -357,6 +358,7 @@ url='#{url}'
357
358
  locations -= [:current, "current"]
358
359
  locations << :current
359
360
  search_paths = IndiferentHash.setup(resource.search_paths)
361
+ choices = []
360
362
  locations.uniq.each do |name|
361
363
  pattern = search_paths[name]
362
364
  pattern = resource.search_paths[pattern] while Symbol === pattern
@@ -370,12 +372,15 @@ url='#{url}'
370
372
  "(?:/(?<REST>.*))?/?$"
371
373
  if m = path.match(regexp)
372
374
  if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == resource.pkgdir
373
- return self[m["TOPLEVEL"]][m["SUBPATH"]][m["REST"]]
375
+ unlocated = ([m["TOPLEVEL"],m["SUBPATH"],m["REST"]] * "/")
376
+ unlocated.gsub!(/\/+/,'/')
377
+ unlocated[self.subdir] = "" if self.subdir
378
+ choices << self.annotate(unlocated)
374
379
  end
375
380
  end
376
381
  end
377
382
  end
378
- nil
383
+ choices.sort_by{|s| s.length }.first
379
384
  end
380
385
  end
381
386
 
@@ -154,7 +154,11 @@ module TSV
154
154
  sheet1 = book.create_worksheet
155
155
  sheet1.name = sheet if sheet
156
156
 
157
- sheet1.row(0).concat fields
157
+ if fields
158
+ sheet1.row(0).concat fields if fields
159
+ else
160
+ sheet1.row(0).concat ["No field info"]
161
+ end
158
162
 
159
163
  rows.each_with_index do |cells,i|
160
164
  sheet1.row(i+1).concat cells
@@ -130,12 +130,12 @@ module TSV
130
130
  keys = parts[key_position].split(@sep2, -1)
131
131
  values = case
132
132
  when field_positions.nil?
133
- parts.tap{|o| o.delete_at key_position}
133
+ parts.tap{|o| o.delete_at key_position}
134
134
  when field_positions.empty?
135
135
  []
136
136
  else
137
137
  parts.values_at *field_positions
138
- end.collect{|value| (value.nil? || value.empty?) ? [] : value.split(@sep2, -1) }
138
+ end.collect{|value| (value.nil? || value.empty?) ? [""] : value.split(@sep2, -1) }
139
139
  [keys, values]
140
140
  end
141
141
 
@@ -432,8 +432,6 @@ def self.add_libdir(dir=nil)
432
432
 
433
433
  def self.ssh_run(server, script = nil)
434
434
  require 'rbbt/util/ssh'
435
- Log.debug "Run ssh script in #{server}:\n#{script}"
436
-
437
435
  SSHLine.ruby(server, script)
438
436
  end
439
437
 
@@ -27,6 +27,9 @@ module Misc
27
27
 
28
28
  def self.format_paragraph(text, size = 80, indent = 0, offset = 0)
29
29
  i = 0
30
+ offset = 0 if offset.nil?
31
+ indent = 0 if indent.nil?
32
+ size = 80 if size.nil?
30
33
  size = size + offset + indent
31
34
  re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/
32
35
  text.split(re).collect do |paragraph|
@@ -22,18 +22,21 @@ module IndiferentHash
22
22
  @_default ||= self.default or self.default_proc
23
23
  end
24
24
 
25
- def [](key)
26
- res = super(key)
25
+ def [](key, *args)
26
+ res = super(key, *args)
27
+ res = IndiferentHash.setup(res) if Hash === res
27
28
  return res unless res.nil? or (_default? and not keys.include? key)
28
29
 
29
30
  case key
30
31
  when Symbol, Module
31
- super(key.to_s)
32
+ res = super(key.to_s, *args)
32
33
  when String
33
- super(key.to_sym)
34
- else
35
- res
34
+ res = super(key.to_sym, *args)
36
35
  end
36
+
37
+ res = IndiferentHash.setup(res) if Hash === res
38
+
39
+ res
37
40
  end
38
41
 
39
42
  def values_at(*key_list)
@@ -275,7 +275,6 @@ module Misc
275
275
 
276
276
 
277
277
  def self.step_file?(path)
278
- return true if defined?(Step) && Step === path.resource
279
278
  return false unless path =~ /\.files(?:\/|$)/
280
279
  parts = path.split("/")
281
280
  job = parts.select{|p| p =~ /\.files$/}.first
@@ -283,9 +282,19 @@ module Misc
283
282
  i = parts.index job
284
283
  begin
285
284
  workflow, task = parts.values_at i - 2, i - 1
286
- Workflow.require_workflow workflow
285
+ _loaded = false
286
+ begin
287
+ Kernel.const_get(workflow)
288
+ rescue
289
+ if ! _loaded
290
+ Workflow.require_workflow workflow
291
+ _loaded = true
292
+ retry
293
+ end
294
+ raise $!
295
+ end
287
296
  #return Kernel.const_get(workflow).tasks.include? task.to_sym
288
- return true
297
+ return parts[i-2..-1] * "/"
289
298
  rescue
290
299
  Log.exception $!
291
300
  end
@@ -293,6 +302,8 @@ module Misc
293
302
  false
294
303
  end
295
304
 
305
+ RBBT_IDENTIFY_PATH = ENV["RBBT_IDENTIFY_PATH"] != 'false'
306
+
296
307
  def self.obj2str(obj)
297
308
  _obj = obj
298
309
  obj = Annotated.purge(obj) if Annotated === obj
@@ -310,18 +321,21 @@ module Misc
310
321
  'false'
311
322
  when Hash
312
323
  "{"<< obj.collect{|k,v| obj2str(k) + '=>' << obj2str(v)}*"," << "}"
313
- when (defined?(Path) and Path)
324
+ when (defined?(Path) && Path)
314
325
  if defined?(Step) && Open.exists?(Step.info_file(obj))
315
326
  obj2str(Workflow.load_step(obj))
316
- elsif step_file?(obj)
317
- "Step file: " + obj
327
+ elsif step_file_path = step_file?(obj)
328
+ "Step file: " + step_file_path
318
329
  else
319
330
  if obj.exists?
331
+ obj = (obj.resource || Rbbt).identify obj if RBBT_IDENTIFY_PATH
320
332
  if obj.directory?
321
333
  files = obj.glob("**/*")
322
- "directory: #{Misc.fingerprint(files)}"
323
- else
334
+ "directory: #{Misc.fingerprint(files.collect{|f| Misc.path_relative_to(obj.find, f)}.sort)}"
335
+ elsif obj.located?
324
336
  "file: " << Open.realpath(obj) << "--" << mtime_str(obj)
337
+ else
338
+ "path: " << obj
325
339
  end
326
340
  else
327
341
  obj + " (file missing)"
@@ -111,7 +111,7 @@ module Misc
111
111
  html = if content.nil?
112
112
  "<#{ tag }#{attr_str}/>"
113
113
  else
114
- "<#{ tag }#{attr_str}>#{ content }</#{ tag }>"
114
+ "<#{ tag }#{attr_str}>#{ content.to_s }</#{ tag }>"
115
115
  end
116
116
 
117
117
  html
@@ -318,9 +318,9 @@ module Misc
318
318
  Open.mkdir dir unless Open.exists?(dir)
319
319
  into_path, into = into, Open.open(into, :mode => 'w')
320
320
  end
321
- into.sync = true if IO === into
321
+ #into.sync = true if IO === into
322
322
  into_close = false unless into.respond_to? :close
323
- io.sync = true
323
+ #io.sync = true
324
324
 
325
325
  begin
326
326
  while c = io.readpartial(BLOCK_SIZE)
@@ -402,7 +402,7 @@ module Misc
402
402
  when (IO === content or StringIO === content or File === content)
403
403
 
404
404
  Open.write(tmp_path) do |f|
405
- f.sync = true
405
+ #f.sync = true
406
406
  while block = content.read(BLOCK_SIZE)
407
407
  f.write block
408
408
  end
@@ -240,7 +240,6 @@ module Open
240
240
  end
241
241
 
242
242
  def self.find_repo_dir(file)
243
- return nil
244
243
  self.repository_dirs.each do |dir|
245
244
  dir = dir + '/' unless dir.chars[-1] == "/"
246
245
 
data/lib/rbbt/util/ssh.rb CHANGED
@@ -37,7 +37,7 @@ class SSHLine
37
37
  @complete_output = true
38
38
  end
39
39
 
40
- def cmd(command)
40
+ def run(command)
41
41
  send_cmd(command)
42
42
  @ssh.loop{ ! @complete_output}
43
43
  if @exit_status.to_i == 0
@@ -51,6 +51,7 @@ class SSHLine
51
51
  @output = ""
52
52
  @complete_output = false
53
53
  cmd = "ruby -e \"#{script.gsub('"','\\"')}\"\n"
54
+ Log.debug "Running ruby on #{@host}:\n#{ script }"
54
55
  @ch.send_data(cmd)
55
56
  @ch.send_data("echo DONECMD: $?\n")
56
57
  @ssh.loop{ !@complete_output }
@@ -61,16 +62,57 @@ class SSHLine
61
62
  end
62
63
  end
63
64
 
65
+ def rbbt(script)
66
+ rbbt_script =<<-EOF
67
+ require 'rbbt-util'
68
+ require 'rbbt/workflow'
69
+
70
+ res = begin
71
+ old_stdout = STDOUT.dup; STDOUT.reopen(STDERR)
72
+ #{script}
73
+ ensure
74
+ STDOUT.reopen(old_stdout)
75
+ end
76
+
77
+ puts Marshal.dump(res)
78
+ EOF
79
+
80
+ m = ruby(rbbt_script)
81
+ Marshal.load m
82
+ end
83
+
84
+ def workflow(workflow, script)
85
+ preamble =<<-EOF
86
+ wf = Workflow.require_workflow('#{workflow}')
87
+ EOF
88
+
89
+ rbbt(preamble + "\n" + script)
90
+ end
91
+
64
92
  @connections = {}
65
93
  def self.open(host, user = nil)
66
94
  @connections[[host, user]] ||= SSHLine.new host, user
67
95
  end
68
96
 
69
- def self.run(server, cmd)
70
- open(server).cmd(cmd)
97
+ def self.run(server, cmd, options = nil)
98
+ cmd = cmd * " " if Array === cmd
99
+ cmd += " " + CMD.process_cmd_options(options) if options
100
+ open(server).run(cmd)
71
101
  end
72
102
 
73
103
  def self.ruby(server, script)
74
104
  open(server).ruby(script)
75
105
  end
106
+
107
+ def self.rbbt(server, script)
108
+ open(server).rbbt(script)
109
+ end
110
+
111
+ def self.workflow(server, workflow, script)
112
+ open(server).workflow(workflow, script)
113
+ end
114
+
115
+ def self.command(server, command, argv = [], options = nil)
116
+ run(server, [command] + argv, options)
117
+ end
76
118
  end
@@ -99,7 +99,7 @@ STDOUT.write res.to_json
99
99
  JSON.parse(json)
100
100
  end
101
101
 
102
- def self.get_raw(url, params)
102
+ def self.get_raw(url, params = {})
103
103
  server, path = parse_url(url)
104
104
  script = path_script(path)
105
105
 
@@ -224,7 +224,7 @@ job.clean
224
224
  def self.upload_dependencies(job_list, server, search_path = 'user', produce_dependencies = false)
225
225
  server, path = parse_url(server) if server =~ /^ssh:\/\//
226
226
 
227
- job_list = [job] unless Array === job_list
227
+ job_list = [job_list] unless Array === job_list
228
228
 
229
229
  all_deps = {}
230
230
  if produce_dependencies
@@ -242,7 +242,6 @@ job.clean
242
242
  all_deps[dep] << job
243
243
  end
244
244
  end
245
- iif all_deps
246
245
 
247
246
  missing_deps = []
248
247
  all_deps.each do |dep,jobs|
@@ -250,10 +249,10 @@ job.clean
250
249
  Log.medium "Producing #{dep.workflow}:#{dep.short_path} dependency for #{Misc.fingerprint jobs}"
251
250
  dep.run(true)
252
251
  missing_deps << dep
253
- end
252
+ end if produce_dependencies
254
253
  Step.wait_for_jobs missing_deps
255
254
 
256
- migrate_dependencies = all_deps.keys.select{|d| d.done? }.collect{|d| d.path }
255
+ migrate_dependencies = all_deps.keys.collect{|d| [d] + d.rec_dependencies + d.input_dependencies }.flatten.select{|d| d.done? }.collect{|d| d.path }
257
256
  Log.medium "Migrating #{migrate_dependencies.length} dependencies from #{Misc.fingerprint job_list} to #{ server }"
258
257
  Step.migrate(migrate_dependencies, search_path, :target => server) if migrate_dependencies.any?
259
258
  end
@@ -312,7 +311,7 @@ job.clean
312
311
 
313
312
  workflow_name = job.workflow.to_s
314
313
  remote_workflow = RemoteWorkflow.new("ssh://#{server}:#{workflow_name}", "#{workflow_name}")
315
- inputs = job.recursive_inputs.to_hash.slice(*job.real_inputs.map{|i| i.to_s})
314
+ inputs = IndiferentHash.setup(job.recursive_inputs.to_hash).slice(*job.real_inputs.map{|i| i.to_s})
316
315
  Log.medium "Relaying dependency #{job.workflow}:#{job.short_path} to #{server} (#{inputs.keys * ", "})"
317
316
 
318
317
  rjob = remote_workflow.job(job.task_name.to_s, job.clean_name, inputs)
@@ -331,6 +330,7 @@ job.clean
331
330
  if options[:migrate]
332
331
  rjobs_job.each do |rjob,job|
333
332
  rjob.produce
333
+ iif [:migrate, job]
334
334
  Step.migrate(Rbbt.identify(job.path), 'user', :source => server)
335
335
  end
336
336
  end
@@ -1,6 +1,6 @@
1
1
  class RemoteStep
2
2
  module SSH
3
- attr_accessor :override_dependencies, :run_type, :slurm_options
3
+ attr_accessor :override_dependencies, :run_type, :slurm_options, :produce_dependencies
4
4
 
5
5
  def init_job(cache_type = nil, other_params = {})
6
6
  return self if @url
@@ -52,11 +52,12 @@ class RemoteStep
52
52
  end
53
53
 
54
54
  def _run
55
- RemoteWorkflow::SSH.upload_dependencies(self, @server)
55
+ RemoteWorkflow::SSH.upload_dependencies(self, @server, 'user', @produce_dependencies)
56
56
  RemoteWorkflow::SSH.run_job(File.join(base_url, task.to_s), @input_id, @base_name)
57
57
  end
58
58
 
59
59
  def _run_slurm
60
+ RemoteWorkflow::SSH.upload_dependencies(self, @server, 'user', @produce_dependencies)
60
61
  RemoteWorkflow::SSH.run_slurm_job(File.join(base_url, task.to_s), @input_id, @base_name, @slurm_options || {})
61
62
  end
62
63
 
@@ -115,7 +116,7 @@ class RemoteStep
115
116
  select{|i| Step === i || (defined?(RemoteStep) && RemoteStep === i) } +
116
117
  inputs.values.flatten.
117
118
  select{|dep| Path === dep && Step === dep.resource }.
118
- select{|dep| ! dep.resource.started? }. # Ignore input_deps already started
119
+ #select{|dep| ! dep.resource.started? }. # Ignore input_deps already started
119
120
  collect{|dep| dep.resource }
120
121
  end
121
122
  end
@@ -188,6 +188,7 @@ class RemoteStep < Step
188
188
  end
189
189
 
190
190
  def file(file)
191
+ init_job
191
192
  @adaptor.get_raw(File.join(url, 'file', file.to_s))
192
193
  end
193
194
 
@@ -107,7 +107,7 @@ class Step
107
107
  canfail = ComputeDependency === job && job.canfail?
108
108
  end
109
109
 
110
- raise_dependency_error(job) if job.error? and not canfail
110
+ Step.raise_dependency_error(job) if job.error? and not canfail
111
111
  end
112
112
 
113
113
  def self.raise_dependency_error(job)
@@ -149,7 +149,7 @@ class Step
149
149
  select{|i| Step === i || (defined?(RemoteStep) && RemoteStep === i) } +
150
150
  recursive_inputs.flatten.
151
151
  select{|dep| Path === dep && Step === dep.resource }.
152
- select{|dep| ! dep.resource.started? }. # Ignore input_deps already started
152
+ #select{|dep| ! dep.resource.started? }. # Ignore input_deps already started
153
153
  collect{|dep| dep.resource }
154
154
  end
155
155
 
@@ -193,7 +193,7 @@ class Step
193
193
 
194
194
  if dependency.error?
195
195
  log_dependency_exec(dependency, :error)
196
- raise_dependency_error dependency
196
+ Step.raise_dependency_error dependency
197
197
  end
198
198
 
199
199
  if dependency.streaming?
@@ -382,7 +382,7 @@ class Step
382
382
 
383
383
  def run_dependencies
384
384
 
385
- rec_dependencies = self.rec_dependencies(true) + input_dependencies
385
+ rec_dependencies = self.rec_dependencies(true) + input_dependencies.reject{|d| d.started? }
386
386
 
387
387
  return if rec_dependencies.empty?
388
388
 
@@ -402,7 +402,7 @@ class Step
402
402
  seen_paths << step.path
403
403
 
404
404
  begin
405
- Step.prepare_for_execution(step) unless step == self
405
+ Step.prepare_for_execution(step) unless step == self
406
406
  rescue DependencyError, DependencyRbbtException
407
407
  raise $! unless canfail_paths.include? step.path
408
408
  end
@@ -423,6 +423,7 @@ class Step
423
423
 
424
424
  produced = []
425
425
  (dependencies + input_dependencies).each do |dep|
426
+ next if dep.started?
426
427
  next unless ComputeDependency === dep
427
428
  if dep.compute == :produce
428
429
  dep.produce
@@ -132,7 +132,7 @@ class Step
132
132
  messages
133
133
  else
134
134
  set_info(:messages, []) if self.respond_to?(:set_info)
135
- end
135
+ end || []
136
136
  end
137
137
 
138
138
  def message(message)
@@ -49,9 +49,9 @@ module Workflow
49
49
  when :nofile
50
50
  inputs[input.to_sym] = Open.realpath(file)
51
51
  when :path_array
52
- inputs[input.to_sym] = Open.read(file).strip.split("\n")
52
+ inputs[input.to_sym] = Open.read(file).strip.split("\n").collect{|p| Path.setup(p) }
53
53
  when :path
54
- inputs[input.to_sym] = Open.read(file).strip.split("\n").first
54
+ inputs[input.to_sym] = Path.setup(Open.read(file).strip.split("\n").first)
55
55
  when :io
56
56
  inputs[input.to_sym] = Open.open(Open.realpath(file))
57
57
  when :io_array
@@ -156,7 +156,7 @@ class Step
156
156
  path = path + '.as_path'
157
157
  end
158
158
  when String
159
- if Misc.is_filename?(value, false)
159
+ if Misc.is_filename?(value, true)
160
160
  value = value.dup
161
161
  value.extend Path
162
162
  return save_input(name, value, type, dir)
@@ -175,7 +175,7 @@ class Step
175
175
  path = path + '.as_path_array'
176
176
  end
177
177
  when String
178
- if Misc.is_filename?(value.first, false)
178
+ if Misc.is_filename?(value.first, true)
179
179
  path = path + '.as_path_array'
180
180
  end
181
181
  when IO
@@ -251,5 +251,4 @@ class Step
251
251
 
252
252
  inputs.keys
253
253
  end
254
-
255
254
  end
@@ -57,7 +57,12 @@ class Step
57
57
  end
58
58
 
59
59
  def workflow
60
- @workflow || info[:workflow] || (@task && @task.respond_to?(:workflow) && @task.workflow) || path.split("/")[-3]
60
+ @workflow ||= begin
61
+ wf = info[:workflow]
62
+ wf = nil if wf == ""
63
+ wf ||= @task.workflow if @task && @task.respond_to?(:workflow)
64
+ wf ||= path.split("/")[-3]
65
+ end
61
66
  end
62
67
 
63
68
 
@@ -296,7 +301,7 @@ class Step
296
301
  res = @result
297
302
  else
298
303
  join if not done?
299
- res = @path.exists? ? Persist.load_file(@path, result_type) : exec
304
+ res = @path.exists? ? Persist.load_file(@path, result_type) : run
300
305
  end
301
306
 
302
307
  if result_description
data/lib/rbbt/workflow.rb CHANGED
@@ -486,7 +486,7 @@ module Workflow
486
486
  if dep_basename.include? "."
487
487
  parts = dep_basename.split(".")
488
488
  extension = [parts.pop]
489
- while parts.last.length <= 4
489
+ while parts.length > 1 && parts.last.length <= 4
490
490
  extension << parts.pop
491
491
  end
492
492
  extension = extension.reverse * "."
@@ -84,5 +84,5 @@ if where.nil? || where == 'all' || path.search_paths.include?(where.to_sym)
84
84
  puts location
85
85
  end
86
86
  else
87
- puts RbbtSSH.command(where, $0, ARGV, options.merge("where" => :all)).read
87
+ puts SSHLine.command(where, $0, ARGV, options.merge("where" => :all))
88
88
  end
@@ -86,5 +86,5 @@ if where.nil? || where == 'all' || path.search_paths.include?(where.to_sym)
86
86
 
87
87
  puts location * "\n"
88
88
  else
89
- puts RbbtSSH.command(where, $0, ARGV, options.merge("where" => :all)).read
89
+ puts SSHLine.command(where, $0, ARGV, options.merge("where" => :all))
90
90
  end
@@ -93,6 +93,8 @@ def fix_options(workflow, task, job_options)
93
93
  TrueClass === value or %w(true TRUE T yes).include? value
94
94
  when :float
95
95
  value.to_f
96
+ when :path
97
+ Path.setup(value)
96
98
  when :integer
97
99
  value.to_i
98
100
  when :text
@@ -419,13 +421,6 @@ begin
419
421
  exit 0
420
422
  end
421
423
 
422
- if tasks = options.delete(:produce)
423
- tasks = tasks.split(",")
424
- produce_cpus = (options[:produce_cpus] || 1)
425
- puts Step.produce_dependencies(job, tasks, prepare_cpus)
426
- exit 0
427
- end
428
-
429
424
  def match_dependencies(queries, dependencies)
430
425
  queries = queries.collect{|q| q.include?("#") ? q.split("#") : q }
431
426
 
@@ -443,6 +438,50 @@ begin
443
438
  matched
444
439
  end
445
440
 
441
+ def replace_relayed_jobs(jobs_to_relay, server, produce_dependencies_for_relay = false, run_type = :run)
442
+ jobs_to_relay.each do |job|
443
+ ComputeDependency.setup(job, :bootstrap)
444
+ next if job.done?
445
+ Log.low "Relaying #{Misc.fingerprint job} to #{server}"
446
+ jmeta = class << job; self; end
447
+
448
+ job.instance_variable_set(:@job, job)
449
+ job.instance_variable_set(:@host, server)
450
+ job.instance_variable_set(:@produce_dependencies, produce_dependencies_for_relay)
451
+
452
+ jmeta.define_method :run do |*args|
453
+ if done?
454
+ load
455
+ else
456
+ RemoteWorkflow::SSH.relay_job_list([@job], @host, :run_type => run_type, :migrate => true, :produce_dependencies => @produce_dependencies)
457
+ Step.migrate(@job, 'user', :source => @host)
458
+ load
459
+ end
460
+ end
461
+ #job.dependencies = []
462
+
463
+ #([job] + job.rec_dependencies).each do |j|
464
+ # next if job.done?
465
+ # jmeta = class << j; self; end
466
+
467
+ # j.instance_variable_set(:@job, job)
468
+ # j.instance_variable_set(:@host, server)
469
+ # j.instance_variable_set(:@produce_dependencies, produce_dependencies_for_relay)
470
+
471
+ # jmeta.define_method :run do |*args|
472
+ # if done?
473
+ # load
474
+ # else
475
+ # RemoteWorkflow::SSH.relay_job_list([@job], @host, :run_type => run_type, :migrate => true, :produce_dependencies => @produce_dependencies)
476
+ # Step.migrate(@job, 'user', :source => @host)
477
+ # load
478
+ # end
479
+ # end
480
+ #end
481
+ end
482
+ end
483
+
484
+
446
485
  if server = options.delete(:relay)
447
486
  require 'rbbt/workflow/remote_workflow'
448
487
  relay_dependencies = options.delete(:relay_dependencies).split(",")
@@ -451,7 +490,7 @@ begin
451
490
  jobs_to_relay = relay_dependencies ? match_dependencies(relay_dependencies, job.rec_dependencies) : [job]
452
491
  jobs_to_relay.reject!{|d| d.done? }
453
492
 
454
- RemoteWorkflow::SSH.relay_job_list(jobs_to_relay, server, :run_type => :run, :migrate => true, :produce_dependencies => produce_dependencies_for_relay)
493
+ replace_relayed_jobs(jobs_to_relay, server, produce_dependencies_for_relay, :run)
455
494
  end
456
495
 
457
496
  if server = options.delete(:slurm_relay)
@@ -461,7 +500,7 @@ begin
461
500
  jobs_to_relay = relay_dependencies ? match_dependencies(relay_dependencies, job.rec_dependencies) : [job]
462
501
  jobs_to_relay.reject!{|d| d.done? }
463
502
 
464
- RemoteWorkflow::SSH.relay_job_list(jobs_to_relay, server, :run_type => :orchestrate, :migrate => true, :produce_dependencies => produce_dependencies_for_relay)
503
+ replace_relayed_jobs(jobs_to_relay, server, produce_dependencies_for_relay, :orchestrate)
465
504
  end
466
505
 
467
506
 
@@ -483,6 +522,14 @@ begin
483
522
  end
484
523
  end
485
524
 
525
+ if tasks = options.delete(:produce)
526
+ tasks = tasks.split(",")
527
+ produce_cpus = (options[:produce_cpus] || 1)
528
+ puts Step.produce_dependencies(job, tasks, produce_cpus)
529
+ exit 0
530
+ end
531
+
532
+
486
533
  if do_fork
487
534
  ENV["RBBT_NO_PROGRESS"] = "true"
488
535
  if detach
@@ -7,6 +7,8 @@ require 'test/unit'
7
7
  module TestResource
8
8
  extend Resource
9
9
 
10
+ self.subdir = 'tmp/tmp-share/resource/TestResource/'
11
+
10
12
  claim tmp.test.google, :url, "http://google.com"
11
13
  claim tmp.test.string, :string, "TEST"
12
14
  claim tmp.test.proc, :proc do
@@ -79,8 +81,8 @@ class TestTSV < Test::Unit::TestCase
79
81
  end
80
82
 
81
83
  def test_libdir
82
- assert File.exist?(TestResource[].share.Rlib["util.R"].find(:lib))
83
- assert File.exist?(TestResource[].share.Rlib["util.R"].find)
84
+ assert File.exist?(Rbbt.share.Rlib["util.R"].find(:lib))
85
+ assert File.exist?(Rbbt.share.Rlib["util.R"].find)
84
86
  end
85
87
 
86
88
  def __test_server
@@ -100,6 +102,9 @@ class TestTSV < Test::Unit::TestCase
100
102
  assert_equal 'share/databases/DATABASE/FILE', Rbbt.identify('/usr/local/share/rbbt/databases/DATABASE/FILE')
101
103
  assert_equal 'share/databases/DATABASE/FILE', Rbbt.identify(File.join(ENV["HOME"], '.rbbt/share/databases/DATABASE/FILE'))
102
104
  assert_equal 'share/databases/DATABASE/FILE', Rbbt.identify('/usr/local/share/rbbt/databases/DATABASE/FILE')
105
+
106
+ assert_equal 'etc/somefile', TestResource.identify(TestResource.etc.somefile.find(:user))
107
+ assert_equal 'etc/somefile', TestResource.identify(TestResource.etc.somefile.find(:local))
103
108
  end
104
109
 
105
110
  end
@@ -199,13 +199,30 @@ row3 A|AA|AAA|AAA B Id3 3
199
199
 
200
200
  def test_unzip
201
201
  content =<<-EOF
202
- #Id ValueA ValueB OtherID
203
- row1 a|A b|B Id1|Id2
204
- row2 aa|aa|AA|AA b1|b2|B1|B2 Id1|Id1|Id2|Id2
202
+ #: :type=:list
203
+ #PMID:Sentence number:TF:TG Transcription Factor (Associated Gene Name) Target Gene (Associated Gene Name) Sign Negation PMID
204
+ 24265317:3:NR1H3:FASN NR1H3 FASN 24265317
205
+ 17522048:0:NR1H3:FASN NR1H3 FASN + 17522048
206
+ 19903962:0:NR1H3:FASN NR1H3 FASN 19903962
207
+ 19903962:7:NR1H3:FASN NR1H3 FASN 19903962
208
+ 22183856:4:NR1H3:FASN NR1H3 FASN 22183856
209
+ 22641099:4:NR1H3:FASN NR1H3 FASN + 22641099
210
+ 23499676:8:NR1H3:FASN NR1H3 FASN + 23499676
211
+ 11790787:5:NR1H3:FASN NR1H3 FASN 11790787
212
+ 11790787:7:NR1H3:FASN NR1H3 FASN + 11790787
213
+ 11790787:9:NR1H3:FASN NR1H3 FASN + 11790787
214
+ 11790787:11:NR1H3:FASN NR1H3 FASN 11790787
215
+ 17522048:1:NR1H3:FASN NR1H3 FASN + 17522048
216
+ 17522048:3:NR1H3:FASN NR1H3 FASN 17522048
217
+ 22160584:1:NR1H3:FASN NR1H3 FASN 22160584
218
+ 22160584:5:NR1H3:FASN NR1H3 FASN + 22160584
219
+ 22160584:8:NR1H3:FASN NR1H3 FASN + 22160584
205
220
  EOF
206
221
 
207
222
  TmpFile.with_file(content) do |filename|
208
- tsv = TSV.open(filename, :sep => /\s+/)
223
+ tsv = TSV.open(filename, :key_field => "Transcription Factor (Associated Gene Name)", :fields => ["Target Gene (Associated Gene Name)", "Sign", "PMID"], :merge => true, :type => :double)
224
+ unzip = tsv.unzip(0,true)
225
+ assert_equal unzip["NR1H3:FASN"][0].length, unzip["NR1H3:FASN"][1].length
209
226
  end
210
227
  end
211
228
 
@@ -69,5 +69,33 @@ A B C D E
69
69
  end
70
70
  end
71
71
 
72
+ def test_merge
73
+ content =<<-EOF
74
+ #: :type=:double
75
+ #PMID:Sentence number:TF:TG Transcription Factor (Associated Gene Name) Target Gene (Associated Gene Name) Sign Negation PMID
76
+ 24265317:3:NR1H3:FASN NR1H3 FASN 24265317
77
+ 17522048:0:NR1H3:FASN NR1H3 FASN + 17522048
78
+ 19903962:0:NR1H3:FASN NR1H3 FASN 19903962
79
+ 19903962:7:NR1H3:FASN NR1H3 FASN 19903962
80
+ 22183856:4:NR1H3:FASN NR1H3 FASN 22183856
81
+ 22641099:4:NR1H3:FASN NR1H3 FASN + 22641099
82
+ 23499676:8:NR1H3:FASN NR1H3 FASN + 23499676
83
+ 11790787:5:NR1H3:FASN NR1H3 FASN 11790787
84
+ 11790787:7:NR1H3:FASN NR1H3 FASN + 11790787
85
+ 11790787:9:NR1H3:FASN NR1H3 FASN + 11790787
86
+ 11790787:11:NR1H3:FASN NR1H3 FASN 11790787
87
+ 17522048:1:NR1H3:FASN NR1H3 FASN + 17522048
88
+ 17522048:3:NR1H3:FASN NR1H3 FASN 17522048
89
+ 22160584:1:NR1H3:FASN NR1H3 FASN 22160584
90
+ 22160584:5:NR1H3:FASN NR1H3 FASN + 22160584
91
+ 22160584:8:NR1H3:FASN NR1H3 FASN + 22160584
92
+ EOF
93
+
94
+ TmpFile.with_file(content) do |filename|
95
+ tsv = TSV.open(filename, :key_field => "Transcription Factor (Associated Gene Name)", :fields => ["Target Gene (Associated Gene Name)", "Sign", "PMID"], :merge => true, :type => :double)
96
+ assert_equal 16, tsv["NR1H3"]["Sign"].length
97
+ end
98
+ end
99
+
72
100
  end
73
101
 
@@ -0,0 +1,14 @@
1
+ require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
+ require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
+
4
+ class TestIndiferentHash < Test::Unit::TestCase
5
+ def test_recursive
6
+ a = {:a => {:b => 1 } }
7
+ IndiferentHash.setup(a)
8
+
9
+ assert IndiferentHash === a["a"]
10
+ assert_equal 1, a[:a]["b"]
11
+ assert_equal 1, a["a"][:b]
12
+ end
13
+ end
14
+
@@ -39,7 +39,7 @@ class TestCmd < Test::Unit::TestCase
39
39
  assert_nothing_raised ProcessFailed do CMD.cmd('ls -fake_option', :no_fail => true, :pipe => true) end
40
40
 
41
41
  assert_raise ProcessFailed do CMD.cmd('fake-command', :stderr => true, :pipe => true).join end
42
- assert_raise ProcessFailed do CMD.cmd('ls -fake_option', :stderr => true, :pipe => true).join end
42
+ assert_raise ConcurrentStreamProcessFailed do CMD.cmd('ls -fake_option', :stderr => true, :pipe => true).join end
43
43
  end
44
44
 
45
45
  def test_pipes
@@ -78,4 +78,10 @@ line33
78
78
  def test_bash
79
79
  puts CMD.bash("awk 'test'")
80
80
  end
81
+
82
+ def test_cmd_error
83
+ assert_raise ConcurrentStreamProcessFailed do
84
+ CMD.cmd_log("ruby -e 'puts 1; STDERR.puts 1; sleep 2; raise'")
85
+ end
86
+ end
81
87
  end
@@ -98,7 +98,7 @@ class TestOpen < Test::Unit::TestCase
98
98
  4
99
99
  EOF
100
100
  TmpFile.with_file(content) do |file|
101
- `bgzip #{file}`
101
+ `gzip #{file}`
102
102
  assert_equal(content, Open.read(file + '.gz'))
103
103
  puts content
104
104
  FileUtils.rm file + '.gz'
@@ -181,8 +181,8 @@ class TestOpen < Test::Unit::TestCase
181
181
  Misc.consume_stream(StringIO.new(text), false, file)
182
182
 
183
183
  assert_equal text, Open.read(file)
184
- assert !File.exist?(file)
185
- assert Open.exists? file
184
+ assert Open.exists?(file)
185
+ refute File.exist?(file)
186
186
  end
187
187
 
188
188
  end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
+ require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
+
4
+ class TestSSH < Test::Unit::TestCase
5
+ def test_marshal
6
+
7
+ assert TrueClass === SSHLine.rbbt('turbo', 'true')
8
+ end
9
+ end
10
+
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.38.0
4
+ version: 5.38.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-11 00:00:00.000000000 Z
11
+ date: 2023-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -530,6 +530,7 @@ files:
530
530
  - test/rbbt/util/misc/test_communication.rb
531
531
  - test/rbbt/util/misc/test_development.rb
532
532
  - test/rbbt/util/misc/test_format.rb
533
+ - test/rbbt/util/misc/test_indiferent_hash.rb
533
534
  - test/rbbt/util/misc/test_lock.rb
534
535
  - test/rbbt/util/misc/test_multipart_payload.rb
535
536
  - test/rbbt/util/misc/test_omics.rb
@@ -556,6 +557,7 @@ files:
556
557
  - test/rbbt/util/test_semaphore.rb
557
558
  - test/rbbt/util/test_simpleDSL.rb
558
559
  - test/rbbt/util/test_simpleopt.rb
560
+ - test/rbbt/util/test_ssh.rb
559
561
  - test/rbbt/util/test_tmpfile.rb
560
562
  - test/rbbt/workflow/step/test_dependencies.rb
561
563
  - test/rbbt/workflow/step/test_save_load_inputs.rb
@@ -587,7 +589,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
587
589
  - !ruby/object:Gem::Version
588
590
  version: '0'
589
591
  requirements: []
590
- rubygems_version: 3.4.8
592
+ rubygems_version: 3.4.13
591
593
  signing_key:
592
594
  specification_version: 4
593
595
  summary: Utilities for the Ruby Bioinformatics Toolkit (rbbt)
@@ -608,6 +610,7 @@ test_files:
608
610
  - test/rbbt/util/test_procpath.rb
609
611
  - test/rbbt/util/python/test_util.rb
610
612
  - test/rbbt/util/misc/test_development.rb
613
+ - test/rbbt/util/misc/test_indiferent_hash.rb
611
614
  - test/rbbt/util/misc/test_omics.rb
612
615
  - test/rbbt/util/misc/test_pipes.rb
613
616
  - test/rbbt/util/misc/test_serialize.rb
@@ -630,6 +633,7 @@ test_files:
630
633
  - test/rbbt/util/test_excel2tsv.rb
631
634
  - test/rbbt/util/test_misc.rb
632
635
  - test/rbbt/util/test_open.rb
636
+ - test/rbbt/util/test_ssh.rb
633
637
  - test/rbbt/util/test_simpleopt.rb
634
638
  - test/rbbt/util/simpleopt/test_parse.rb
635
639
  - test/rbbt/util/simpleopt/test_setup.rb