rbbt-util 5.6.2 → 5.6.3
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/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
|