rbbt-util 5.6.2 → 5.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rbbt +18 -2
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +3 -3
- data/lib/rbbt/util/semaphore.rb +50 -1
- data/lib/rbbt/util/simpleopt/accessor.rb +50 -0
- data/lib/rbbt/util/simpleopt/doc.rb +90 -0
- data/lib/rbbt/util/simpleopt/get.rb +41 -0
- data/lib/rbbt/util/simpleopt/parse.rb +44 -0
- data/lib/rbbt/util/simpleopt.rb +5 -242
- data/lib/rbbt/workflow/accessor.rb +8 -4
- data/lib/rbbt/workflow/usage.rb +2 -3
- data/share/rbbt_commands/workflow/task +23 -14
- data/test/rbbt/util/simpleopt/test_get.rb +12 -0
- data/test/rbbt/util/simpleopt/test_parse.rb +10 -0
- data/test/rbbt/util/test_semaphore.rb +18 -0
- data/test/rbbt/util/test_simpleopt.rb +2 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecea1d091627d32a02327ea8a0eee78b099f13f0
|
4
|
+
data.tar.gz: a2ebf3798cb4ee454a3050307816b5d6ad46747d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff9269d0314aa934653a32231706cf665209e411773b4e174228623697ec01fd223a626059d87c2ed2209b9ba33779c019719b2d17b795b0e68fca4e8ea8ba15
|
7
|
+
data.tar.gz: e34f7b523daa44e076da779f3ed6d79733214770fceb5a16e8643f1e8db6aa035523c0925656adfee7b1d5f9d8713e4c026ea6905064927de2cbcddb26095d68
|
data/bin/rbbt
CHANGED
@@ -57,11 +57,13 @@ begin
|
|
57
57
|
load dir[command].find
|
58
58
|
exit 0
|
59
59
|
else
|
60
|
-
|
61
|
-
puts
|
60
|
+
error = "Command '#{command }' not understood"
|
62
61
|
break
|
63
62
|
end
|
64
63
|
end
|
64
|
+
rescue ParameterException
|
65
|
+
error = $!.message
|
66
|
+
backtrace = $!.backtrace
|
65
67
|
ensure
|
66
68
|
if options[:profile]
|
67
69
|
result = RubyProf.stop
|
@@ -83,4 +85,18 @@ puts
|
|
83
85
|
commands(prev).each do |command|
|
84
86
|
puts " " << command
|
85
87
|
end
|
88
|
+
|
89
|
+
if error
|
90
|
+
puts
|
91
|
+
puts Term::ANSIColor.red("Error executing '#{ [File.basename($0), prev, command].compact.flatten * " " }':")
|
92
|
+
puts
|
93
|
+
puts error
|
94
|
+
if backtrace
|
95
|
+
puts
|
96
|
+
puts Term::ANSIColor.red("Backtrace:")
|
97
|
+
puts
|
98
|
+
puts backtrace * "\n"
|
99
|
+
end
|
100
|
+
puts
|
101
|
+
end
|
86
102
|
|
@@ -12,7 +12,7 @@ module Persist
|
|
12
12
|
database = CONNECTIONS[path] ||= tokyocabinet_class.new
|
13
13
|
|
14
14
|
flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
|
15
|
-
database.close
|
15
|
+
database.close
|
16
16
|
|
17
17
|
if !database.open(path, flags)
|
18
18
|
ecode = database.ecode
|
@@ -93,7 +93,7 @@ module Persist
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def write_and_read
|
96
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
96
|
+
lock_filename = Persist.persistence_path(persistence_path + '.write', {:dir => TSV.lock_dir})
|
97
97
|
Misc.lock(lock_filename) do
|
98
98
|
write if @closed or not write?
|
99
99
|
res = begin
|
@@ -106,7 +106,7 @@ module Persist
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def write_and_close
|
109
|
-
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
109
|
+
lock_filename = Persist.persistence_path(persistence_path + '.write', {:dir => TSV.lock_dir})
|
110
110
|
Misc.lock(lock_filename) do
|
111
111
|
write if @closed or not write?
|
112
112
|
res = begin
|
data/lib/rbbt/util/semaphore.rb
CHANGED
@@ -88,5 +88,54 @@ void post_semaphore(char* name){
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
|
+
def self.thread_each_on_semaphore(elems, size)
|
93
|
+
mutex = Mutex.new
|
94
|
+
count = 0
|
95
|
+
cv = ConditionVariable.new
|
96
|
+
wait_mutex = Mutex.new
|
97
|
+
|
98
|
+
begin
|
99
|
+
|
100
|
+
threads = []
|
101
|
+
wait_mutex.synchronize do
|
102
|
+
threads = elems.collect do |elem|
|
103
|
+
Thread.new(elem) do |elem|
|
104
|
+
|
105
|
+
continue = false
|
106
|
+
mutex.synchronize do
|
107
|
+
while not continue do
|
108
|
+
if count < size
|
109
|
+
continue = true
|
110
|
+
count += 1
|
111
|
+
end
|
112
|
+
mutex.sleep 1 unless continue
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
begin
|
117
|
+
yield elem
|
118
|
+
rescue Interrupt
|
119
|
+
Log.error "Thread was aborted while processing: #{Misc.fingerprint elem}"
|
120
|
+
raise $!
|
121
|
+
ensure
|
122
|
+
mutex.synchronize do
|
123
|
+
count -= 1
|
124
|
+
cv.signal if mutex.locked?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
threads.each do |thread|
|
132
|
+
thread.join
|
133
|
+
end
|
134
|
+
rescue Exception
|
135
|
+
Log.exception $!
|
136
|
+
Log.info "Ensuring threads are dead: #{threads.length}"
|
137
|
+
threads.each do |thread| thread.kill end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
92
141
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module SOPT
|
3
|
+
class << self
|
4
|
+
attr_accessor :inputs, :input_shortcuts, :input_types, :input_descriptions, :input_defaults
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.all
|
8
|
+
@all ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.shortcuts
|
12
|
+
@shortcuts ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.inputs
|
16
|
+
@inputs ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.input_shortcuts
|
20
|
+
@input_shortcuts ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.input_types
|
24
|
+
@input_types ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.input_descriptions
|
28
|
+
@input_descriptions ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.input_defaults
|
32
|
+
@input_defaults ||= {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.reset
|
36
|
+
@shortcuts = {}
|
37
|
+
@all = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.delete_inputs(inputs)
|
41
|
+
inputs.each do |input|
|
42
|
+
input = input.to_s
|
43
|
+
self.shortcuts.delete self.input_shortcuts.delete(input)
|
44
|
+
self.inputs.delete input
|
45
|
+
self.input_types.delete input
|
46
|
+
self.input_defaults.delete input
|
47
|
+
self.input_descriptions.delete input
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module SOPT
|
2
|
+
|
3
|
+
class << self
|
4
|
+
attr_accessor :command, :summary, :synopsys, :description
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.command
|
8
|
+
@command ||= File.basename($0)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.summary
|
12
|
+
@summary ||= ""
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.synopsys
|
16
|
+
@synopsys ||= begin
|
17
|
+
"#{command} " <<
|
18
|
+
inputs.collect{|name|
|
19
|
+
"[" << input_format(name, input_types[name] || :string, input_defaults[name], input_shortcuts[name]).sub(/:$/,'') << "]"
|
20
|
+
} * " "
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.description
|
25
|
+
@description ||= "Missing"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.input_format(name, type = nil, default = nil, short = nil)
|
29
|
+
input_str = (short.nil? or short.empty?) ? "--#{name}" : "-#{short}, --#{name}"
|
30
|
+
input_str << case type
|
31
|
+
when nil
|
32
|
+
"#{default != nil ? " (default '#{default}')" : ""}:"
|
33
|
+
when :boolean
|
34
|
+
"[=false]#{default != nil ? " (default '#{default}')" : ""}:"
|
35
|
+
when :tsv, :text
|
36
|
+
"=<filename.#{type}|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
37
|
+
when :array
|
38
|
+
"=<string[,string]*|filename.list|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
39
|
+
else
|
40
|
+
"=<#{ type }>#{default != nil ? " (default '#{default}')" : ""}:"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
|
45
|
+
type = description = default = nil
|
46
|
+
shortcut = ""
|
47
|
+
inputs.collect do |name|
|
48
|
+
name = name.to_s
|
49
|
+
|
50
|
+
type = input_types[name] unless input_types.nil?
|
51
|
+
description = input_descriptions[name] unless input_descriptions.nil?
|
52
|
+
default = input_defaults[name] unless input_defaults.nil?
|
53
|
+
|
54
|
+
case input_shortcuts
|
55
|
+
when nil, FalseClass
|
56
|
+
shortcut = nil
|
57
|
+
when Hash
|
58
|
+
shortcut = input_shortcuts[name]
|
59
|
+
when TrueClass
|
60
|
+
shortcut = fix_shortcut(name[0], name)
|
61
|
+
end
|
62
|
+
|
63
|
+
type = :string if type.nil?
|
64
|
+
register(shortcut, name, type, description) unless self.inputs.include? name
|
65
|
+
|
66
|
+
str = " * " << SOPT.input_format(name, type.to_sym, default, shortcut) << "\n"
|
67
|
+
str << " " << description << "\n" if description and not description.empty?
|
68
|
+
str
|
69
|
+
end * "\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.doc
|
73
|
+
doc = <<-EOF
|
74
|
+
#{command}(1) -- #{summary}
|
75
|
+
#{"=" * (command.length + summary.length + 7)}
|
76
|
+
|
77
|
+
## SYNOPSYS
|
78
|
+
|
79
|
+
#{synopsys}
|
80
|
+
|
81
|
+
## DESCRIPTION
|
82
|
+
|
83
|
+
#{description}
|
84
|
+
|
85
|
+
## OPTIONS
|
86
|
+
|
87
|
+
#{input_doc(inputs, input_types, input_descriptions, input_defaults, input_shortcuts)}
|
88
|
+
EOF
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SOPT
|
2
|
+
def self.consume(args = ARGV)
|
3
|
+
i = 0
|
4
|
+
values = {}
|
5
|
+
while i < args.length do
|
6
|
+
current = args[i]
|
7
|
+
if m = current.match(/--?(.+?)(?:=(.+))?$/)
|
8
|
+
key = $1
|
9
|
+
value = $2
|
10
|
+
|
11
|
+
input = inputs.include?(key)? key : shortcuts[key]
|
12
|
+
|
13
|
+
if input.nil?
|
14
|
+
i += 1
|
15
|
+
next
|
16
|
+
else
|
17
|
+
args.delete_at i
|
18
|
+
end
|
19
|
+
else
|
20
|
+
i += 1
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
if input_types[input] == :string
|
25
|
+
value = args.delete_at(i) if value.nil?
|
26
|
+
values[input] = value
|
27
|
+
else
|
28
|
+
values[input] = %w(F false FALSE no).include?(value)? false : true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
IndiferentHash.setup values
|
33
|
+
|
34
|
+
values
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get(opt_str)
|
38
|
+
SOPT.parse(opt_str)
|
39
|
+
SOPT.consume(ARGV)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rbbt/util/simpleopt/accessor'
|
2
|
+
module SOPT
|
3
|
+
def self.fix_shortcut(short, long)
|
4
|
+
return short unless short and shortcuts.include?(short)
|
5
|
+
|
6
|
+
chars = long.chars.to_a
|
7
|
+
current = [chars.shift]
|
8
|
+
short = current * ""
|
9
|
+
|
10
|
+
while shortcuts.include? short
|
11
|
+
next_letter = chars.shift
|
12
|
+
return nil if next_letter.nil?
|
13
|
+
current << next_letter
|
14
|
+
short = current * ""
|
15
|
+
end
|
16
|
+
|
17
|
+
short
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.register(short, long, asterisk, description)
|
21
|
+
short = fix_shortcut(short, long)
|
22
|
+
shortcuts[short] = long if short
|
23
|
+
inputs << long
|
24
|
+
input_shortcuts[long] = short
|
25
|
+
input_descriptions[long] = description
|
26
|
+
input_types[long] = asterisk ? :string : :boolean
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse(opt_str)
|
30
|
+
info = {}
|
31
|
+
|
32
|
+
inputs = []
|
33
|
+
opt_str.split(/[:\n]+/).each do |entry|
|
34
|
+
entry.strip!
|
35
|
+
next if entry.empty?
|
36
|
+
names, _sep, description = entry.partition /\s+/
|
37
|
+
short, long, asterisk = names.match(/\s*(?:-(.+))?(?:--(.+?))([*])?$/).values_at 1,2,3
|
38
|
+
|
39
|
+
inputs << long
|
40
|
+
register short, long, asterisk, description
|
41
|
+
end
|
42
|
+
inputs
|
43
|
+
end
|
44
|
+
end
|
data/lib/rbbt/util/simpleopt.rb
CHANGED
@@ -1,244 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class << self
|
6
|
-
attr_accessor :command, :summary, :synopsys, :description
|
7
|
-
attr_accessor :inputs, :input_shortcuts, :input_types, :input_descriptions, :input_defaults
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.command
|
11
|
-
@command ||= File.basename($0)
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.summary
|
15
|
-
@summary ||= ""
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.synopsys
|
19
|
-
@synopsys ||= begin
|
20
|
-
"#{command} " <<
|
21
|
-
inputs.collect{|name|
|
22
|
-
"[" << input_format(name, input_types[name] || :string, input_defaults[name], input_shortcuts[name]).sub(/:$/,'') << "]"
|
23
|
-
} * " "
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.description
|
28
|
-
@description ||= "Missing"
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.shortcuts
|
32
|
-
@shortcuts ||= []
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.delete_inputs(inputs)
|
36
|
-
inputs.each do |input|
|
37
|
-
input = input.to_s
|
38
|
-
self.shortcuts.delete self.input_shortcuts.delete(input)
|
39
|
-
self.inputs.delete input
|
40
|
-
self.input_types.delete input
|
41
|
-
self.input_defaults.delete input
|
42
|
-
self.input_descriptions.delete input
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.all
|
47
|
-
@all ||= {}
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.inputs
|
51
|
-
@inputs ||= []
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.input_shortcuts
|
55
|
-
@input_shortcuts ||= {}
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.input_types
|
59
|
-
@input_types ||= {}
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.input_descriptions
|
63
|
-
@input_descriptions ||= {}
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.input_defaults
|
67
|
-
@input_defaults ||= {}
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.reset
|
71
|
-
@shortcuts = []
|
72
|
-
@all = {}
|
73
|
-
end
|
74
|
-
|
75
|
-
#{{{ PARSING
|
76
|
-
|
77
|
-
def self.record(info)
|
78
|
-
input = info[:long].sub("--", '')
|
79
|
-
inputs << input
|
80
|
-
input_types[input] = info[:arg] ? :string : :boolean
|
81
|
-
input_descriptions[input] = info[:description]
|
82
|
-
input_defaults[input] = info[:default]
|
83
|
-
input_shortcuts[input] = info[:short]? info[:short].sub("-",'') : nil
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.short_for(name)
|
87
|
-
short = []
|
88
|
-
chars = name.to_s.chars.to_a
|
89
|
-
|
90
|
-
short << chars.shift
|
91
|
-
shortcuts = input_shortcuts.values.compact.flatten
|
92
|
-
while shortcuts.include? short * "" and chars.any?
|
93
|
-
short << chars.shift
|
94
|
-
end
|
95
|
-
return nil if chars.empty?
|
96
|
-
|
97
|
-
short * ""
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
def self.name(info)
|
102
|
-
(info[:long] || info[:short]).sub(/^-*/,'')
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.parse(opts)
|
106
|
-
info = {}
|
107
|
-
|
108
|
-
opts.split(/[:\n]+/).each do |opt|
|
109
|
-
next if opt.strip.empty?
|
110
|
-
|
111
|
-
short, long = opt.strip.sub(/(^[^\s]*)\*/,'\1').split('--').values_at(0,1)
|
112
|
-
long, short = short, nil if long.nil?
|
113
|
-
|
114
|
-
if long.index(" ")
|
115
|
-
long, description = long.match(/^([^\s]+)\s+(.*)/).values_at 1, 2
|
116
|
-
else
|
117
|
-
description = nil
|
118
|
-
end
|
119
|
-
|
120
|
-
i= { :arg => !!opt.match(/^[^\s]*\*/) }
|
121
|
-
|
122
|
-
i[:short] = short unless short.nil? || short.empty?
|
123
|
-
i[:long] = '--' + long unless long.nil? || long.empty?
|
124
|
-
i[:description] = description unless description.nil? || description.empty?
|
125
|
-
|
126
|
-
if shortcuts.include? short
|
127
|
-
i[:short] = short_for(i[:long])
|
128
|
-
Log.debug{ "Short for #{ long } is taken. Changed to #{i[:short]}" }
|
129
|
-
else
|
130
|
-
shortcuts << i[:short] if short
|
131
|
-
end
|
1
|
+
require 'rbbt/util/simpleopt/accessor'
|
2
|
+
require 'rbbt/util/simpleopt/doc'
|
3
|
+
require 'rbbt/util/simpleopt/parse'
|
4
|
+
require 'rbbt/util/simpleopt/get'
|
132
5
|
|
133
|
-
|
134
|
-
|
135
|
-
info[name(i)] = i
|
136
|
-
end
|
137
|
-
|
138
|
-
info
|
139
|
-
end
|
140
|
-
|
141
|
-
def self.get(opts)
|
142
|
-
info = parse(opts)
|
143
|
-
|
144
|
-
switches = {}
|
145
|
-
info.each do |name, i|
|
146
|
-
switches[i[:short]] = name if i[:short]
|
147
|
-
switches[i[:long]] = name if i[:long]
|
148
|
-
end
|
149
|
-
|
150
|
-
options = Hash.new(false)
|
151
|
-
rest = []
|
152
|
-
|
153
|
-
index = 0
|
154
|
-
while index < ARGV.length do
|
155
|
-
orig_arg = ARGV[index]
|
156
|
-
|
157
|
-
if orig_arg =~ /=/
|
158
|
-
arg, value = orig_arg.match(/(.*?)=(.*)/).values_at 1, 2
|
159
|
-
else
|
160
|
-
arg = orig_arg
|
161
|
-
value = nil
|
162
|
-
end
|
163
|
-
|
164
|
-
if switches.include? arg
|
165
|
-
name = switches[arg]
|
166
|
-
i = info[name]
|
167
|
-
if i[:arg]
|
168
|
-
if value.nil?
|
169
|
-
value = ARGV[index + 1]
|
170
|
-
index += 1
|
171
|
-
end
|
172
|
-
options[name.to_sym] = value
|
173
|
-
else
|
174
|
-
options[name.to_sym] = value == "false" ? false : true
|
175
|
-
end
|
176
|
-
else
|
177
|
-
rest << orig_arg
|
178
|
-
end
|
179
|
-
index += 1
|
180
|
-
end
|
181
|
-
|
182
|
-
ARGV.delete_if do true end
|
183
|
-
rest.each do |e| ARGV << e end
|
184
|
-
|
185
|
-
options
|
186
|
-
end
|
187
|
-
|
188
|
-
#{{{ DOCUMENTATION
|
189
|
-
|
190
|
-
def self.input_format(name, type = nil, default = nil, short = "")
|
191
|
-
short = short_for(name) if not short.nil? and short.empty?
|
192
|
-
|
193
|
-
input_str = short.nil? ? "--#{name}" : "-#{short}, --#{name}"
|
194
|
-
input_str << case type
|
195
|
-
when nil
|
196
|
-
"#{default != nil ? " (default '#{default}')" : ""}:"
|
197
|
-
when :boolean
|
198
|
-
"[=false]#{default != nil ? " (default '#{default}')" : ""}:"
|
199
|
-
when :tsv, :text
|
200
|
-
"=<filename.#{type}|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
201
|
-
when :array
|
202
|
-
"=<string[,string]*|filename.list|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
203
|
-
else
|
204
|
-
"=<#{ type }>#{default != nil ? " (default '#{default}')" : ""}:"
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
|
209
|
-
type = description = default = nil
|
210
|
-
shortcut = ""
|
211
|
-
inputs.collect do |name|
|
212
|
-
|
213
|
-
type = input_types[name] unless input_types.nil?
|
214
|
-
description = input_descriptions[name] unless input_descriptions.nil?
|
215
|
-
default = input_defaults[name] unless input_defaults.nil?
|
216
|
-
shortcut = input_shortcuts[name] unless input_shortcuts.nil?
|
217
|
-
|
218
|
-
type = :string if type.nil?
|
219
|
-
|
220
|
-
str = " * " << SOPT.input_format(name, type.to_sym, default, shortcut) << "\n"
|
221
|
-
str << " " << description << "\n" if description and not description.empty?
|
222
|
-
str
|
223
|
-
end * "\n"
|
224
|
-
end
|
225
|
-
|
226
|
-
def self.doc
|
227
|
-
doc = <<-EOF
|
228
|
-
#{command}(1) -- #{summary}
|
229
|
-
#{"=" * (command.length + summary.length + 7)}
|
230
|
-
|
231
|
-
## SYNOPSYS
|
232
|
-
|
233
|
-
#{synopsys}
|
234
|
-
|
235
|
-
## DESCRIPTION
|
236
|
-
|
237
|
-
#{description}
|
238
|
-
|
239
|
-
## OPTIONS
|
240
|
-
|
241
|
-
#{input_doc(inputs, input_types, input_descriptions, input_defaults, input_shortcuts)}
|
242
|
-
EOF
|
243
|
-
end
|
6
|
+
module SOPT
|
244
7
|
end
|
@@ -260,19 +260,23 @@ module Workflow
|
|
260
260
|
end
|
261
261
|
|
262
262
|
def rec_input_defaults(taskname)
|
263
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_defaults}
|
263
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_defaults}.
|
264
|
+
tap{|h| IndiferentHash.setup(h)}
|
264
265
|
end
|
265
266
|
|
266
267
|
def rec_input_types(taskname)
|
267
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_types}
|
268
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_types}.
|
269
|
+
tap{|h| IndiferentHash.setup(h)}
|
268
270
|
end
|
269
271
|
|
270
272
|
def rec_input_descriptions(taskname)
|
271
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_descriptions}
|
273
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_descriptions}.
|
274
|
+
tap{|h| IndiferentHash.setup(h)}
|
272
275
|
end
|
273
276
|
|
274
277
|
def rec_input_options(taskname)
|
275
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_options}
|
278
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_options}.
|
279
|
+
tap{|h| IndiferentHash.setup(h)}
|
276
280
|
end
|
277
281
|
|
278
282
|
def real_dependencies(task, jobname, inputs, dependencies)
|
data/lib/rbbt/workflow/usage.rb
CHANGED
@@ -4,8 +4,7 @@ module Task
|
|
4
4
|
def doc(deps = nil)
|
5
5
|
puts "## #{ name }:"
|
6
6
|
puts "\n" << description if description and not description.empty?
|
7
|
-
puts
|
8
|
-
puts SOPT.input_doc(inputs, input_types, input_descriptions, input_defaults)
|
7
|
+
puts SOPT.input_doc(inputs, input_types, input_descriptions, input_defaults, true)
|
9
8
|
|
10
9
|
if deps and deps.any?
|
11
10
|
puts
|
@@ -14,7 +13,7 @@ module Task
|
|
14
13
|
deps.each do |dep|
|
15
14
|
puts " #{dep.name}:"
|
16
15
|
puts
|
17
|
-
puts SOPT.input_doc(dep.inputs, dep.input_types, dep.input_descriptions, dep.input_defaults)
|
16
|
+
puts SOPT.input_doc(dep.inputs, dep.input_types, dep.input_descriptions, dep.input_defaults, true)
|
18
17
|
puts
|
19
18
|
end
|
20
19
|
end
|
@@ -108,17 +108,19 @@ end
|
|
108
108
|
|
109
109
|
options = SOPT.get <<EOF
|
110
110
|
-h--help Show this help:
|
111
|
+
-wd--workdir* Change the working directory of the workflow:
|
111
112
|
-as--array_separator* Change the character that separates elements of Arrays, ',', '|', or '\\n' by default:
|
113
|
+
-jn--jobname* Job name to use. The name 'Default' is used by default:
|
114
|
+
-pn--printname Print the name of the job and exit without starting it:
|
112
115
|
-cl--clean Clean the last step of the job so that it gets recomputed:
|
113
116
|
-rcl--recursive_clean Clean the last step and its dependencies to recompute the job completely:
|
114
|
-
|
115
|
-
|
117
|
+
--fork Run job asyncronously:
|
118
|
+
--exec Run job with no persistence:
|
116
119
|
-O--output* Save job result into file:
|
117
|
-
-pn--printname Print the name of the job and exit without starting it:
|
118
120
|
-jf--job_file* Output one of the job produced files:
|
121
|
+
-ljf--list_job_files List all the files produced in that step:
|
119
122
|
--info Show the job info:
|
120
123
|
--provenance Report the jobs provenance:
|
121
|
-
--fork Run job asyncronously:
|
122
124
|
EOF
|
123
125
|
|
124
126
|
workflow = ARGV.shift
|
@@ -132,6 +134,8 @@ do_fork = !!options.delete(:fork)
|
|
132
134
|
do_exec = !!options.delete(:exec)
|
133
135
|
clean = !!options.delete(:clean)
|
134
136
|
recursive_clean = !!options.delete(:recursive_clean)
|
137
|
+
out = options.include?(:output) ? File.open(options[:output], 'wb') : STDOUT
|
138
|
+
|
135
139
|
$array_separator = options.delete(:array_separator)
|
136
140
|
|
137
141
|
# Get workflow
|
@@ -157,13 +161,14 @@ namespace = nil, nil
|
|
157
161
|
case
|
158
162
|
when task.nil?
|
159
163
|
usage workflow
|
160
|
-
|
161
|
-
|
162
|
-
namespace =
|
164
|
+
# Can not remember what this was
|
165
|
+
#when (task =~ /\./)
|
166
|
+
# namespace, task = options.delete(:task).split('.')
|
167
|
+
# namespace = Misc.string2const(namespace)
|
163
168
|
else
|
164
169
|
task_name = task.to_sym
|
165
170
|
task = workflow.tasks[task_name]
|
166
|
-
raise "Task not found: #{ task_name }" if task.nil?
|
171
|
+
raise ParameterException, "Task not found: #{ task_name }" if task.nil?
|
167
172
|
end
|
168
173
|
|
169
174
|
usage workflow, task if help
|
@@ -206,13 +211,13 @@ begin
|
|
206
211
|
res = job.exec
|
207
212
|
case
|
208
213
|
when Array === res
|
209
|
-
puts res * "\n"
|
214
|
+
out.puts res * "\n"
|
210
215
|
when TSV === res
|
211
|
-
puts res
|
216
|
+
out.puts res
|
212
217
|
when Hash === res
|
213
|
-
puts res.to_yaml
|
218
|
+
out.puts res.to_yaml
|
214
219
|
else
|
215
|
-
puts res
|
220
|
+
out.puts res
|
216
221
|
end
|
217
222
|
exit 0
|
218
223
|
end
|
@@ -247,10 +252,14 @@ rescue ParameterException
|
|
247
252
|
usage(workflow, task, $!.message, $!.backtrace)
|
248
253
|
end
|
249
254
|
|
250
|
-
|
255
|
+
|
256
|
+
if options.delete(:list_job_files)
|
257
|
+
out.puts job.files * "\n"
|
258
|
+
exit 0
|
259
|
+
end
|
251
260
|
|
252
261
|
if job_file = options.delete(:job_file)
|
253
|
-
out.puts
|
262
|
+
out.puts job.file(job_file).read
|
254
263
|
exit 0
|
255
264
|
end
|
256
265
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
|
2
|
+
require 'rbbt/util/simpleopt/parse'
|
3
|
+
require 'rbbt/util/simpleopt/get'
|
4
|
+
|
5
|
+
class TestSOPTParse < Test::Unit::TestCase
|
6
|
+
def test_consume
|
7
|
+
SOPT.parse("-f--first* first arg:-f--fun")
|
8
|
+
args = "-f myfile --fun".split(" ")
|
9
|
+
assert_equal "myfile", SOPT.consume(args)[:first]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
|
2
|
+
require 'rbbt/util/simpleopt/parse'
|
3
|
+
|
4
|
+
class TestSOPTParse < Test::Unit::TestCase
|
5
|
+
def test_parse
|
6
|
+
SOPT.parse("-f--first* first arg:-f--fun")
|
7
|
+
assert_equal "fun", SOPT.shortcuts["fu"]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'test_helper.rb')
|
2
|
+
require 'rbbt/util/semaphore'
|
3
|
+
|
4
|
+
class TestRbbtSemaphore < Test::Unit::TestCase
|
5
|
+
def test_thread
|
6
|
+
times = 50
|
7
|
+
TmpFile.with_file do |dir|
|
8
|
+
Path.setup(dir)
|
9
|
+
FileUtils.mkdir_p dir
|
10
|
+
RbbtSemaphore.thread_each_on_semaphore((1..times).to_a, 25){|elem|
|
11
|
+
sleep rand
|
12
|
+
Open.write(dir[elem], "test")
|
13
|
+
}
|
14
|
+
assert_equal times, dir.glob.length
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -5,6 +5,7 @@ require 'test/unit'
|
|
5
5
|
class TestSOPT < Test::Unit::TestCase
|
6
6
|
|
7
7
|
def test_cmd_option_string
|
8
|
-
|
8
|
+
SOPT.parse("-h--help:-to--tsv-options")
|
9
|
+
assert_equal "tsv-options", SOPT.shortcuts["to"]
|
9
10
|
end
|
10
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.6.
|
4
|
+
version: 5.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -196,6 +196,10 @@ files:
|
|
196
196
|
- lib/rbbt/util/semaphore.rb
|
197
197
|
- lib/rbbt/util/simpleDSL.rb
|
198
198
|
- lib/rbbt/util/simpleopt.rb
|
199
|
+
- lib/rbbt/util/simpleopt/accessor.rb
|
200
|
+
- lib/rbbt/util/simpleopt/doc.rb
|
201
|
+
- lib/rbbt/util/simpleopt/get.rb
|
202
|
+
- lib/rbbt/util/simpleopt/parse.rb
|
199
203
|
- lib/rbbt/util/tar.rb
|
200
204
|
- lib/rbbt/util/task/job.rb
|
201
205
|
- lib/rbbt/util/tmpfile.rb
|
@@ -267,6 +271,8 @@ files:
|
|
267
271
|
- test/rbbt/tsv/test_index.rb
|
268
272
|
- test/rbbt/tsv/test_manipulate.rb
|
269
273
|
- test/rbbt/tsv/test_util.rb
|
274
|
+
- test/rbbt/util/simpleopt/test_get.rb
|
275
|
+
- test/rbbt/util/simpleopt/test_parse.rb
|
270
276
|
- test/rbbt/util/test_R.rb
|
271
277
|
- test/rbbt/util/test_chain_methods.rb
|
272
278
|
- test/rbbt/util/test_cmd.rb
|
@@ -275,6 +281,7 @@ files:
|
|
275
281
|
- test/rbbt/util/test_filecache.rb
|
276
282
|
- test/rbbt/util/test_misc.rb
|
277
283
|
- test/rbbt/util/test_open.rb
|
284
|
+
- test/rbbt/util/test_semaphore.rb
|
278
285
|
- test/rbbt/util/test_simpleDSL.rb
|
279
286
|
- test/rbbt/util/test_simpleopt.rb
|
280
287
|
- test/rbbt/util/test_tmpfile.rb
|
@@ -309,6 +316,8 @@ test_files:
|
|
309
316
|
- test/rbbt/test_workflow.rb
|
310
317
|
- test/rbbt/resource/test_path.rb
|
311
318
|
- test/rbbt/util/test_cmd.rb
|
319
|
+
- test/rbbt/util/simpleopt/test_get.rb
|
320
|
+
- test/rbbt/util/simpleopt/test_parse.rb
|
312
321
|
- test/rbbt/util/test_chain_methods.rb
|
313
322
|
- test/rbbt/util/test_simpleDSL.rb
|
314
323
|
- test/rbbt/util/test_open.rb
|
@@ -317,6 +326,7 @@ test_files:
|
|
317
326
|
- test/rbbt/util/test_simpleopt.rb
|
318
327
|
- test/rbbt/util/test_excel2tsv.rb
|
319
328
|
- test/rbbt/util/test_filecache.rb
|
329
|
+
- test/rbbt/util/test_semaphore.rb
|
320
330
|
- test/rbbt/util/test_misc.rb
|
321
331
|
- test/rbbt/util/test_tmpfile.rb
|
322
332
|
- test/rbbt/test_association.rb
|