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 +4 -4
- data/lib/rbbt/annotations.rb +2 -0
- data/lib/rbbt/persist.rb +2 -2
- data/lib/rbbt/resource.rb +7 -2
- data/lib/rbbt/tsv/excel.rb +5 -1
- data/lib/rbbt/tsv/parser.rb +2 -2
- data/lib/rbbt/util/misc/development.rb +0 -2
- data/lib/rbbt/util/misc/format.rb +3 -0
- data/lib/rbbt/util/misc/indiferent_hash.rb +9 -6
- data/lib/rbbt/util/misc/inspect.rb +22 -8
- data/lib/rbbt/util/misc/options.rb +1 -1
- data/lib/rbbt/util/misc/pipes.rb +3 -3
- data/lib/rbbt/util/open.rb +0 -1
- data/lib/rbbt/util/ssh.rb +45 -3
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +6 -6
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +4 -3
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +1 -0
- data/lib/rbbt/workflow/step/dependencies.rb +6 -5
- data/lib/rbbt/workflow/step/info.rb +1 -1
- data/lib/rbbt/workflow/step/save_load_inputs.rb +4 -5
- data/lib/rbbt/workflow/step.rb +7 -2
- data/lib/rbbt/workflow.rb +1 -1
- data/share/rbbt_commands/resource/find +1 -1
- data/share/rbbt_commands/resource/glob +1 -1
- data/share/rbbt_commands/workflow/task +56 -9
- data/test/rbbt/test_resource.rb +7 -2
- data/test/rbbt/tsv/test_accessor.rb +21 -4
- data/test/rbbt/tsv/test_parser.rb +28 -0
- data/test/rbbt/util/misc/test_indiferent_hash.rb +14 -0
- data/test/rbbt/util/test_cmd.rb +7 -1
- data/test/rbbt/util/test_open.rb +3 -3
- data/test/rbbt/util/test_ssh.rb +10 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1121593dec25c29d7986047727d555ed0e75df6b158f9f1332764ad4886462c5
|
4
|
+
data.tar.gz: c8e39ef65e23445cf5d0c8817af961a9206016c5e3665d87e042f0fadec2b8df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22c87766544a52c9c6f0d6da369422a452f553d1a61b82a54674f676a3867a6c1d29028c2efd031563f982cdadbce56d36950c8e100bd34ac2a7e95b39af8a58
|
7
|
+
data.tar.gz: 0a79edc89dad388bca9b94dfeccba1df64c4294e84c4f19743608038e55f8800181911d787980adae3ec1c715a993430ccbf2bc07d6212485b89843ada93de74
|
data/lib/rbbt/annotations.rb
CHANGED
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
|
-
|
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
|
-
|
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
|
-
|
383
|
+
choices.sort_by{|s| s.length }.first
|
379
384
|
end
|
380
385
|
end
|
381
386
|
|
data/lib/rbbt/tsv/excel.rb
CHANGED
@@ -154,7 +154,11 @@ module TSV
|
|
154
154
|
sheet1 = book.create_worksheet
|
155
155
|
sheet1.name = sheet if sheet
|
156
156
|
|
157
|
-
|
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
|
data/lib/rbbt/tsv/parser.rb
CHANGED
@@ -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
|
-
|
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
|
|
@@ -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
|
-
|
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
|
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)
|
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: " +
|
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
|
-
|
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)"
|
data/lib/rbbt/util/misc/pipes.rb
CHANGED
@@ -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
|
data/lib/rbbt/util/open.rb
CHANGED
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
|
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
|
-
|
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 = [
|
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
|
@@ -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
|
@@ -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,
|
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,
|
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
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -57,7 +57,12 @@ class Step
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def workflow
|
60
|
-
@workflow
|
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) :
|
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 * "."
|
@@ -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
|
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
|
-
|
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
|
-
|
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
|
data/test/rbbt/test_resource.rb
CHANGED
@@ -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?(
|
83
|
-
assert File.exist?(
|
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
|
-
|
203
|
-
|
204
|
-
|
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, :
|
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
|
+
|
data/test/rbbt/util/test_cmd.rb
CHANGED
@@ -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
|
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
|
data/test/rbbt/util/test_open.rb
CHANGED
@@ -98,7 +98,7 @@ class TestOpen < Test::Unit::TestCase
|
|
98
98
|
4
|
99
99
|
EOF
|
100
100
|
TmpFile.with_file(content) do |file|
|
101
|
-
`
|
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
|
185
|
-
|
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.
|
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-
|
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.
|
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
|