rbbt-util 5.38.0 → 5.38.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|