scout-gear 7.3.0 → 8.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +44 -16
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/bin/scout +21 -7
- data/doc/lib/scout/path.md +35 -0
- data/doc/lib/scout/workflow/task.md +13 -0
- data/lib/rbbt-scout.rb +1 -0
- data/lib/scout/cmd.rb +24 -25
- data/lib/scout/concurrent_stream.rb +59 -39
- data/lib/scout/config.rb +1 -1
- data/lib/scout/exceptions.rb +10 -0
- data/lib/scout/log/color.rb +15 -12
- data/lib/scout/log/progress/report.rb +8 -6
- data/lib/scout/log/progress/util.rb +61 -54
- data/lib/scout/log/progress.rb +1 -1
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +115 -52
- data/lib/scout/meta_extension.rb +47 -6
- data/lib/scout/misc/digest.rb +12 -3
- data/lib/scout/misc/format.rb +24 -7
- data/lib/scout/misc/insist.rb +1 -1
- data/lib/scout/misc/monitor.rb +22 -0
- data/lib/scout/misc/system.rb +58 -0
- data/lib/scout/named_array.rb +73 -3
- data/lib/scout/offsite/ssh.rb +171 -0
- data/lib/scout/offsite/step.rb +83 -0
- data/lib/scout/offsite/sync.rb +55 -0
- data/lib/scout/offsite.rb +3 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +9 -2
- data/lib/scout/open/remote.rb +16 -1
- data/lib/scout/open/stream.rb +146 -83
- data/lib/scout/open/util.rb +22 -3
- data/lib/scout/open.rb +5 -4
- data/lib/scout/path/find.rb +24 -11
- data/lib/scout/path/util.rb +40 -0
- data/lib/scout/persist/serialize.rb +19 -6
- data/lib/scout/persist.rb +29 -13
- data/lib/scout/resource/path.rb +57 -0
- data/lib/scout/resource/produce.rb +0 -8
- data/lib/scout/resource/util.rb +12 -5
- data/lib/scout/tmpfile.rb +7 -8
- data/lib/scout/tsv/attach.rb +177 -0
- data/lib/scout/tsv/change_id.rb +40 -0
- data/lib/scout/tsv/dumper.rb +74 -46
- data/lib/scout/tsv/index.rb +85 -87
- data/lib/scout/tsv/open.rb +160 -85
- data/lib/scout/tsv/parser.rb +142 -80
- data/lib/scout/tsv/path.rb +1 -2
- data/lib/scout/tsv/persist/adapter.rb +15 -45
- data/lib/scout/tsv/persist/fix_width_table.rb +3 -0
- data/lib/scout/tsv/persist/tokyocabinet.rb +6 -1
- data/lib/scout/tsv/persist.rb +4 -0
- data/lib/scout/tsv/stream.rb +204 -0
- data/lib/scout/tsv/transformer.rb +152 -0
- data/lib/scout/tsv/traverse.rb +96 -92
- data/lib/scout/tsv/util/filter.rb +9 -0
- data/lib/scout/tsv/util/reorder.rb +81 -0
- data/lib/scout/tsv/util/select.rb +78 -33
- data/lib/scout/tsv/util/unzip.rb +86 -0
- data/lib/scout/tsv/util.rb +60 -11
- data/lib/scout/tsv.rb +34 -4
- data/lib/scout/work_queue/socket.rb +6 -1
- data/lib/scout/work_queue/worker.rb +5 -2
- data/lib/scout/work_queue.rb +51 -20
- data/lib/scout/workflow/definition.rb +23 -3
- data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
- data/lib/scout/workflow/deployment.rb +1 -0
- data/lib/scout/workflow/step/dependencies.rb +56 -10
- data/lib/scout/workflow/step/file.rb +5 -0
- data/lib/scout/workflow/step/info.rb +40 -7
- data/lib/scout/workflow/step/load.rb +1 -1
- data/lib/scout/workflow/step/provenance.rb +9 -7
- data/lib/scout/workflow/step/status.rb +43 -0
- data/lib/scout/workflow/step.rb +160 -49
- data/lib/scout/workflow/task/dependencies.rb +114 -0
- data/lib/scout/workflow/task/inputs.rb +40 -32
- data/lib/scout/workflow/task.rb +38 -102
- data/lib/scout/workflow/usage.rb +48 -18
- data/lib/scout/workflow.rb +4 -2
- data/lib/scout-gear.rb +2 -0
- data/lib/scout.rb +6 -0
- data/scout-gear.gemspec +52 -23
- data/scout_commands/doc +37 -0
- data/scout_commands/find +1 -0
- data/scout_commands/offsite +30 -0
- data/scout_commands/update +29 -0
- data/scout_commands/workflow/info +15 -3
- data/scout_commands/workflow/install +102 -0
- data/scout_commands/workflow/task +57 -9
- data/test/scout/offsite/test_ssh.rb +15 -0
- data/test/scout/offsite/test_step.rb +33 -0
- data/test/scout/offsite/test_sync.rb +36 -0
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/open/test_stream.rb +60 -58
- data/test/scout/path/test_find.rb +10 -1
- data/test/scout/resource/test_path.rb +6 -0
- data/test/scout/resource/test_produce.rb +15 -0
- data/test/scout/test_meta_extension.rb +25 -0
- data/test/scout/test_named_array.rb +24 -0
- data/test/scout/test_persist.rb +9 -2
- data/test/scout/test_tsv.rb +229 -2
- data/test/scout/test_work_queue.rb +65 -41
- data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
- data/test/scout/tsv/test_attach.rb +227 -0
- data/test/scout/tsv/test_change_id.rb +98 -0
- data/test/scout/tsv/test_dumper.rb +1 -1
- data/test/scout/tsv/test_index.rb +49 -3
- data/test/scout/tsv/test_open.rb +160 -2
- data/test/scout/tsv/test_parser.rb +33 -2
- data/test/scout/tsv/test_persist.rb +2 -0
- data/test/scout/tsv/test_stream.rb +200 -0
- data/test/scout/tsv/test_transformer.rb +120 -0
- data/test/scout/tsv/test_traverse.rb +88 -3
- data/test/scout/tsv/test_util.rb +1 -0
- data/test/scout/tsv/util/test_reorder.rb +94 -0
- data/test/scout/tsv/util/test_select.rb +25 -11
- data/test/scout/tsv/util/test_unzip.rb +112 -0
- data/test/scout/work_queue/test_socket.rb +0 -1
- data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
- data/test/scout/workflow/step/test_dependencies.rb +68 -0
- data/test/scout/workflow/step/test_info.rb +18 -0
- data/test/scout/workflow/step/test_status.rb +30 -0
- data/test/scout/workflow/task/test_dependencies.rb +355 -0
- data/test/scout/workflow/task/test_inputs.rb +67 -14
- data/test/scout/workflow/test_definition.rb +18 -0
- data/test/scout/workflow/test_documentation.rb +24 -0
- data/test/scout/workflow/test_step.rb +112 -3
- data/test/scout/workflow/test_task.rb +0 -151
- data/test/scout/workflow/test_usage.rb +33 -6
- data/test/test_scout.rb +9 -0
- metadata +100 -8
- data/scout_commands/workflow/task_old +0 -706
@@ -0,0 +1,204 @@
|
|
1
|
+
module TSV
|
2
|
+
def self.paste_streams(streams, type: nil, sort: nil, sort_memory: nil, sep: nil, preamble: nil, header: nil, same_fields: nil, fix_flat: nil, all_match: nil, field_prefix: nil)
|
3
|
+
|
4
|
+
streams = streams.collect do |stream|
|
5
|
+
case stream
|
6
|
+
when(defined? Step and Step)
|
7
|
+
stream.stream
|
8
|
+
when Path
|
9
|
+
stream.open
|
10
|
+
when TSV::Dumper
|
11
|
+
stream.stream
|
12
|
+
else
|
13
|
+
stream
|
14
|
+
end
|
15
|
+
end.compact
|
16
|
+
|
17
|
+
num_streams = streams.length
|
18
|
+
|
19
|
+
streams = streams.collect do |stream|
|
20
|
+
Open.sort_stream(stream, memory: sort_memory)
|
21
|
+
end if sort
|
22
|
+
|
23
|
+
begin
|
24
|
+
|
25
|
+
lines =[]
|
26
|
+
fields =[]
|
27
|
+
sizes =[]
|
28
|
+
key_fields =[]
|
29
|
+
input_options =[]
|
30
|
+
empty =[]
|
31
|
+
preambles =[]
|
32
|
+
parser_types =[]
|
33
|
+
|
34
|
+
type ||= :double
|
35
|
+
|
36
|
+
streams = streams.collect do |stream|
|
37
|
+
|
38
|
+
parser = TSV::Parser.new stream, type: type
|
39
|
+
|
40
|
+
sfields = parser.fields
|
41
|
+
|
42
|
+
if field_prefix
|
43
|
+
index = streams.index stream
|
44
|
+
prefix = field_prefix[index]
|
45
|
+
|
46
|
+
sfields = sfields.collect{|f|[prefix, f]* ":"}
|
47
|
+
end
|
48
|
+
|
49
|
+
first_line = parser.first_line
|
50
|
+
first_line = nil if first_line == ""
|
51
|
+
|
52
|
+
lines << first_line
|
53
|
+
key_fields << parser.key_field
|
54
|
+
fields << sfields
|
55
|
+
sizes << sfields.length if sfields
|
56
|
+
input_options << parser.options
|
57
|
+
preambles << parser.preamble if preamble and not parser.preamble.empty?
|
58
|
+
parser_types << parser.type
|
59
|
+
|
60
|
+
empty << stream if parser.first_line.nil? || parser.first_line.empty?
|
61
|
+
|
62
|
+
stream
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
all_fields = fields.dup
|
67
|
+
|
68
|
+
key_field = key_fields.compact.first
|
69
|
+
|
70
|
+
if same_fields
|
71
|
+
fields = fields.first
|
72
|
+
else
|
73
|
+
fields = fields.compact.flatten
|
74
|
+
end
|
75
|
+
|
76
|
+
options = input_options.first
|
77
|
+
type ||= options[:type]
|
78
|
+
type ||= :list if type == :single
|
79
|
+
type ||= :double if type == :flat
|
80
|
+
|
81
|
+
preamble_txt = case preamble
|
82
|
+
when TrueClass
|
83
|
+
preambles * "\n"
|
84
|
+
when String
|
85
|
+
if preamble[0]== '+'
|
86
|
+
preambles * "\n" + "\n" + preamble[1..-1]
|
87
|
+
else
|
88
|
+
preamble
|
89
|
+
end
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
empty_pos = empty.collect{|stream| streams.index stream}
|
95
|
+
|
96
|
+
keys =[]
|
97
|
+
parts =[]
|
98
|
+
lines.each_with_index do |line,i|
|
99
|
+
if line.nil? || line.empty?
|
100
|
+
keys[i]= nil
|
101
|
+
parts[i]= nil
|
102
|
+
else
|
103
|
+
vs = line.chomp.split(sep, -1)
|
104
|
+
key, *p = vs
|
105
|
+
keys[i]= key
|
106
|
+
parts[i]= p
|
107
|
+
end
|
108
|
+
sizes[i]||= parts[i].length-1 unless parts[i].nil?
|
109
|
+
end
|
110
|
+
done_streams =[]
|
111
|
+
|
112
|
+
dumper = TSV::Dumper.new key_field: key_field, fields: fields, type: type
|
113
|
+
dumper.init
|
114
|
+
|
115
|
+
t = Thread.new do
|
116
|
+
Thread.report_on_exception = false
|
117
|
+
Thread.current["name"] = "Paste streams"
|
118
|
+
|
119
|
+
last_min = nil
|
120
|
+
while lines.reject{|line| line.nil?}.any?
|
121
|
+
min = keys.compact.sort.first
|
122
|
+
break if min.nil?
|
123
|
+
new_values =[]
|
124
|
+
|
125
|
+
skip = all_match && keys.uniq !=[min]
|
126
|
+
|
127
|
+
keys.each_with_index do |key,i|
|
128
|
+
case key
|
129
|
+
when min
|
130
|
+
new_values << parts[i]
|
131
|
+
|
132
|
+
begin
|
133
|
+
line = lines[i]= begin
|
134
|
+
streams[i].gets
|
135
|
+
rescue
|
136
|
+
Log.exception $!
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
if line.nil?
|
140
|
+
keys[i]= nil
|
141
|
+
parts[i]= nil
|
142
|
+
else
|
143
|
+
k, *p = line.chomp.split(sep, -1)
|
144
|
+
raise TryAgain if k == keys[i]
|
145
|
+
keys[i]= k
|
146
|
+
parts[i]= p.collect{|e| e.nil? ? "" : e}
|
147
|
+
end
|
148
|
+
rescue TryAgain
|
149
|
+
keys[i]= nil
|
150
|
+
parts[i]= nil
|
151
|
+
Log.debug "Skipping repeated key in stream #{i}: #{keys[i]}"
|
152
|
+
retry
|
153
|
+
end
|
154
|
+
else
|
155
|
+
p = [nil] * sizes[i]
|
156
|
+
new_values << p
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
next if skip
|
161
|
+
|
162
|
+
if same_fields
|
163
|
+
new_values_same = []
|
164
|
+
new_values.each do |list|
|
165
|
+
list.each_with_index do |l,i|
|
166
|
+
new_values_same[i] ||= []
|
167
|
+
new_values_same[i] << l
|
168
|
+
end
|
169
|
+
end
|
170
|
+
new_values = new_values_same
|
171
|
+
else
|
172
|
+
new_values = new_values.inject([]){|acc,l| acc.concat l }
|
173
|
+
end
|
174
|
+
|
175
|
+
dumper.add min, new_values
|
176
|
+
end
|
177
|
+
|
178
|
+
dumper.close
|
179
|
+
|
180
|
+
streams.each do |stream|
|
181
|
+
stream.close if stream.respond_to?(:close) && ! stream.closed?
|
182
|
+
stream.join if stream.respond_to? :join
|
183
|
+
end
|
184
|
+
end
|
185
|
+
rescue Aborted
|
186
|
+
Log.error "Aborted pasting streams #{streams.inspect}: #{$!.message}"
|
187
|
+
streams.each do |stream|
|
188
|
+
stream.abort if stream.respond_to? :abort
|
189
|
+
end
|
190
|
+
raise $!
|
191
|
+
rescue Exception
|
192
|
+
Log.error "Exception pasting streams #{streams.inspect}: #{$!.message}"
|
193
|
+
streams.each do |stream|
|
194
|
+
stream.abort if stream.respond_to? :abort
|
195
|
+
end
|
196
|
+
raise $!
|
197
|
+
end
|
198
|
+
|
199
|
+
Thread.pass until t["name"]
|
200
|
+
|
201
|
+
ConcurrentStream.setup(dumper.stream, threads: [t])
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module TSV
|
2
|
+
class Transformer
|
3
|
+
attr_accessor :unnamed, :parser, :dumper
|
4
|
+
|
5
|
+
def initialize(parser, dumper = nil, unnamed: false)
|
6
|
+
if TSV::Parser === parser
|
7
|
+
@parser = parser
|
8
|
+
elsif TSV === parser
|
9
|
+
@parser = parser
|
10
|
+
else
|
11
|
+
@parser = TSV::Parser.new parser
|
12
|
+
end
|
13
|
+
@unnamed = unnamed
|
14
|
+
if dumper.nil?
|
15
|
+
@dumper = TSV::Dumper.new(@parser)
|
16
|
+
@dumper.sep = "\t"
|
17
|
+
else
|
18
|
+
@dumper = dumper
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def key_field=(key_field)
|
23
|
+
@dumper.key_field = key_field
|
24
|
+
end
|
25
|
+
|
26
|
+
def fields=(fields)
|
27
|
+
@dumper.fields = fields
|
28
|
+
end
|
29
|
+
|
30
|
+
def type=(type)
|
31
|
+
@dumper.type = type
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
@dumper.type
|
36
|
+
end
|
37
|
+
|
38
|
+
def sep=(sep)
|
39
|
+
@dumper.sep = sep
|
40
|
+
end
|
41
|
+
|
42
|
+
def include?(*args)
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def key_field
|
47
|
+
@dumper.key_field
|
48
|
+
end
|
49
|
+
|
50
|
+
def fields
|
51
|
+
@dumper.fields
|
52
|
+
end
|
53
|
+
|
54
|
+
def all_fields
|
55
|
+
return nil if fields.nil?
|
56
|
+
[key_field] + fields
|
57
|
+
end
|
58
|
+
|
59
|
+
def options
|
60
|
+
@dumper.options
|
61
|
+
end
|
62
|
+
|
63
|
+
def identify_field(name)
|
64
|
+
TSV.identify_field key_field, fields, name
|
65
|
+
end
|
66
|
+
|
67
|
+
def traverse(*args, **kwargs, &block)
|
68
|
+
kwargs[:into] = @dumper
|
69
|
+
kwargs[:bar] = "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @target}" if TrueClass === kwargs[:bar]
|
70
|
+
@dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
|
71
|
+
Log.debug "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @dumper}"
|
72
|
+
Open.traverse(@parser, *args, **kwargs) do |k,v|
|
73
|
+
NamedArray.setup(v, @parser.fields, k) unless @unnamed
|
74
|
+
block.call k, v
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def each(*args, **kwargs, &block)
|
79
|
+
kwargs[:into] = @dumper
|
80
|
+
kwargs[:bar] = "Transform #{Log.fingerprint @parser} into #{Log.fingerprint @target}" if TrueClass === kwargs[:bar]
|
81
|
+
@dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
|
82
|
+
Open.traverse(@parser, *args, **kwargs) do |k,v|
|
83
|
+
NamedArray.setup(v, @parser.fields, k) unless @unnamed
|
84
|
+
block.call k, v
|
85
|
+
[k, v]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def with_unnamed
|
90
|
+
begin
|
91
|
+
old_unnamed = @unnamed
|
92
|
+
@unnamed = true
|
93
|
+
yield
|
94
|
+
ensure
|
95
|
+
@unnamed = old_unnamed
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def []=(key, value)
|
100
|
+
@dumper.init if @dumper.respond_to?(:init) && ! @dumper.initialized
|
101
|
+
@dumper.add key, value
|
102
|
+
end
|
103
|
+
|
104
|
+
def stream
|
105
|
+
@dumper.stream
|
106
|
+
end
|
107
|
+
|
108
|
+
def tsv(*args)
|
109
|
+
TSV === @dumper ? @dumper : TSV.open(stream, *args)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_list
|
114
|
+
res = self.annotate({})
|
115
|
+
transformer = Transformer.new self, res
|
116
|
+
transformer.type = :list
|
117
|
+
transformer.traverse do |k,v|
|
118
|
+
case self.type
|
119
|
+
when :single
|
120
|
+
[k, [v]]
|
121
|
+
when :double
|
122
|
+
[k, v.collect{|v| v.first }]
|
123
|
+
when :flat
|
124
|
+
[k, v.slice(0,1)]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
res
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_single
|
131
|
+
res = self.annotate({})
|
132
|
+
transformer = Transformer.new self, res
|
133
|
+
transformer.type = :single
|
134
|
+
transformer.traverse do |k,v|
|
135
|
+
v = v.first while Array === v
|
136
|
+
[k, v]
|
137
|
+
end
|
138
|
+
res
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_flat
|
142
|
+
res = self.annotate({})
|
143
|
+
transformer = Transformer.new self, res
|
144
|
+
transformer.type = :flat
|
145
|
+
transformer.traverse do |k,v|
|
146
|
+
v = Array === v ? v.flatten : [v]
|
147
|
+
[k, v]
|
148
|
+
end
|
149
|
+
res
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
data/lib/scout/tsv/traverse.rb
CHANGED
@@ -1,22 +1,14 @@
|
|
1
1
|
require_relative 'parser'
|
2
2
|
module TSV
|
3
|
-
def
|
4
|
-
return :key if name == :key || key_field.start_with?(name.to_s)
|
5
|
-
name.collect!{|n| key_field == n ? :key : n } if Array === name
|
6
|
-
NamedArray.identify_name(fields, name)
|
7
|
-
end
|
8
|
-
|
9
|
-
def identify_field(name)
|
10
|
-
TSV.identify_field(@key_field, @fields, name)
|
11
|
-
end
|
12
|
-
|
13
|
-
def traverse(key_field_pos = :key, fields_pos = nil, type: nil, one2one: false, unnamed: false, key_field: nil, fields: nil, &block)
|
3
|
+
def traverse(key_field_pos = :key, fields_pos = nil, type: nil, one2one: false, unnamed: false, key_field: nil, fields: nil, bar: false, cast: nil, select: nil, &block)
|
14
4
|
key_field = key_field_pos if key_field.nil?
|
15
|
-
fields = fields_pos if fields.nil?
|
5
|
+
fields = fields_pos.dup if fields.nil?
|
16
6
|
type = @type if type.nil?
|
17
7
|
key_pos = self.identify_field(key_field)
|
8
|
+
fields = self.all_fields if fields == :all
|
18
9
|
fields = [fields] unless fields.nil? || Array === fields
|
19
|
-
positions = fields.nil? ? nil : self.identify_field(fields)
|
10
|
+
positions = fields.nil? || fields == :all ? nil : self.identify_field(fields)
|
11
|
+
|
20
12
|
|
21
13
|
if key_pos == :key
|
22
14
|
key_name = @key_field
|
@@ -33,7 +25,7 @@ module TSV
|
|
33
25
|
field_names = @fields
|
34
26
|
elsif positions.nil? && key_pos != :key
|
35
27
|
field_names = @fields.dup
|
36
|
-
field_names.delete_at key_pos
|
28
|
+
field_names.delete_at key_pos unless fields == :all
|
37
29
|
elsif positions.include?(:key)
|
38
30
|
field_names = positions.collect{|p| p == :key ? @key_field : @fields[p] }
|
39
31
|
else
|
@@ -43,98 +35,110 @@ module TSV
|
|
43
35
|
key_index = positions.index :key if positions
|
44
36
|
positions.delete :key if positions
|
45
37
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
if key_pos != :key
|
50
|
-
values = values.dup
|
51
|
-
key = values.delete_at(key_pos)
|
52
|
-
end
|
53
|
-
else
|
54
|
-
orig_key = key
|
55
|
-
key = values[key_pos] if key_pos != :key
|
38
|
+
log_message = "Traverse #{Log.fingerprint self}"
|
39
|
+
Log.debug log_message
|
40
|
+
bar = log_message if TrueClass === bar
|
56
41
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
42
|
+
Log::ProgressBar.with_obj_bar(self, bar) do |bar|
|
43
|
+
with_unnamed unnamed do
|
44
|
+
each do |key,values|
|
45
|
+
bar.tick if bar
|
46
|
+
values = [values] if @type == :single
|
47
|
+
if positions.nil?
|
48
|
+
if key_pos != :key
|
49
|
+
values = values.dup
|
50
|
+
key = values.delete_at(key_pos)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
orig_key = key
|
54
|
+
key = values[key_pos] if key_pos != :key
|
55
|
+
|
56
|
+
values = values.values_at(*positions)
|
57
|
+
if key_index
|
58
|
+
if @type == :double
|
59
|
+
values.insert key_index, [orig_key]
|
60
|
+
else
|
61
|
+
values.insert key_index, orig_key
|
62
|
+
end
|
63
|
+
end
|
63
64
|
end
|
64
|
-
end
|
65
|
-
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
if
|
70
|
-
|
71
|
-
if
|
72
|
-
|
66
|
+
values = TSV.cast_value(values, cast) if cast
|
67
|
+
|
68
|
+
if Array === key
|
69
|
+
if @type == :double && one2one
|
70
|
+
if one2one == :strict
|
71
|
+
key.each_with_index do |key_i,i|
|
72
|
+
if type == :double
|
73
|
+
v_i = values.collect{|v| [v[i]] }
|
74
|
+
else
|
75
|
+
v_i = values.collect{|v| v[i] }
|
76
|
+
end
|
77
|
+
yield key_i, v_i
|
78
|
+
end
|
73
79
|
else
|
74
|
-
|
80
|
+
key.each_with_index do |key_i,i|
|
81
|
+
if type == :double
|
82
|
+
v_i = values.collect{|v| [v[i] || v.first] }
|
83
|
+
else
|
84
|
+
v_i = values.collect{|v| v[i] || v.first }
|
85
|
+
end
|
86
|
+
yield key_i, v_i, @fields
|
87
|
+
end
|
88
|
+
end
|
89
|
+
else
|
90
|
+
key.each_with_index do |key_i, i|
|
91
|
+
if type == :double
|
92
|
+
yield key_i, values
|
93
|
+
elsif type == :list
|
94
|
+
yield key_i, values.collect{|v| v[i] }
|
95
|
+
elsif type == :flat
|
96
|
+
yield key_i, values.flatten
|
97
|
+
elsif type == :single
|
98
|
+
yield key_i, values.first
|
99
|
+
end
|
75
100
|
end
|
76
|
-
yield key_i, v_i
|
77
101
|
end
|
78
102
|
else
|
79
|
-
|
80
|
-
if type == :
|
81
|
-
|
103
|
+
if type == @type
|
104
|
+
if type == :single
|
105
|
+
yield key, values.first
|
82
106
|
else
|
83
|
-
|
107
|
+
yield key, values
|
108
|
+
end
|
109
|
+
else
|
110
|
+
case [type, @type]
|
111
|
+
when [:double, :list]
|
112
|
+
yield key, values.collect{|v| [v] }
|
113
|
+
when [:double, :flat]
|
114
|
+
yield key, [values]
|
115
|
+
when [:double, :single]
|
116
|
+
yield key, [values]
|
117
|
+
when [:list, :double]
|
118
|
+
yield key, values.collect{|v| v.first }
|
119
|
+
when [:list, :flat]
|
120
|
+
yield key, [values.first]
|
121
|
+
when [:list, :single]
|
122
|
+
yield key, values
|
123
|
+
when [:flat, :double]
|
124
|
+
yield key, values.flatten
|
125
|
+
when [:flat, :list]
|
126
|
+
yield key, values.flatten
|
127
|
+
when [:flat, :single]
|
128
|
+
yield key, values
|
129
|
+
when [:single, :double]
|
130
|
+
yield key, values.flatten.first
|
131
|
+
when [:single, :list]
|
132
|
+
yield key, values.first
|
133
|
+
when [:single, :flat]
|
134
|
+
yield key, values.first
|
84
135
|
end
|
85
|
-
yield key_i, v_i
|
86
|
-
end
|
87
|
-
end
|
88
|
-
else
|
89
|
-
key.each_with_index do |key_i, i|
|
90
|
-
if type == :double
|
91
|
-
yield key_i, values
|
92
|
-
elsif type == :list
|
93
|
-
yield key_i, values.collect{|v| v[i] }
|
94
|
-
elsif type == :flat
|
95
|
-
yield key_i, values.flatten
|
96
|
-
elsif type == :single
|
97
|
-
yield key_i, values.first
|
98
136
|
end
|
99
137
|
end
|
100
138
|
end
|
101
|
-
else
|
102
|
-
if type == @type
|
103
|
-
if type == :single
|
104
|
-
yield key, values.first
|
105
|
-
else
|
106
|
-
yield key, values
|
107
|
-
end
|
108
|
-
else
|
109
|
-
case [type, @type]
|
110
|
-
when [:double, :list]
|
111
|
-
yield key, values.collect{|v| [v] }
|
112
|
-
when [:double, :flat]
|
113
|
-
yield key, [values]
|
114
|
-
when [:double, :single]
|
115
|
-
yield key, [values]
|
116
|
-
when [:list, :double]
|
117
|
-
yield key, values.collect{|v| v.first }
|
118
|
-
when [:list, :flat]
|
119
|
-
yield key, [values.first]
|
120
|
-
when [:list, :single]
|
121
|
-
yield key, values
|
122
|
-
when [:flat, :double]
|
123
|
-
yield key, values.flatten
|
124
|
-
when [:flat, :list]
|
125
|
-
yield key, values.flatten
|
126
|
-
when [:flat, :single]
|
127
|
-
yield key, values
|
128
|
-
when [:single, :double]
|
129
|
-
yield key, values.flatten.first
|
130
|
-
when [:single, :list]
|
131
|
-
yield key, values.first
|
132
|
-
when [:single, :flat]
|
133
|
-
yield key, values.first
|
134
|
-
end
|
135
|
-
end
|
136
139
|
end
|
137
140
|
end
|
141
|
+
|
138
142
|
|
139
143
|
[key_name, field_names]
|
140
144
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
module TSV
|
4
|
+
def reorder(key_field = nil, fields = nil, merge: true, one2one: true, **kwargs)
|
5
|
+
res = self.annotate({})
|
6
|
+
res.type = kwargs[:type] if kwargs.include?(:type)
|
7
|
+
kwargs[:one2one] = one2one
|
8
|
+
key_field_name, field_names = traverse key_field, fields, **kwargs do |k,v|
|
9
|
+
if @type == :double && merge && res.include?(k)
|
10
|
+
current = res[k]
|
11
|
+
if merge == :concat
|
12
|
+
v.each_with_index do |new,i|
|
13
|
+
next if new.empty?
|
14
|
+
current[i].concat(new)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
merged = []
|
18
|
+
v.each_with_index do |new,i|
|
19
|
+
next if new.empty?
|
20
|
+
merged[i] = current[i] + new
|
21
|
+
end
|
22
|
+
res[k] = merged
|
23
|
+
end
|
24
|
+
else
|
25
|
+
res[k] = v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
res.key_field = key_field_name
|
29
|
+
res.fields = field_names
|
30
|
+
res
|
31
|
+
end
|
32
|
+
|
33
|
+
def slice(fields, **kwargs)
|
34
|
+
reorder :key, fields, **kwargs
|
35
|
+
end
|
36
|
+
|
37
|
+
def column(field, **kwargs)
|
38
|
+
new_type = case type
|
39
|
+
when :double, :flat
|
40
|
+
:flat
|
41
|
+
else
|
42
|
+
:single
|
43
|
+
end
|
44
|
+
|
45
|
+
kwargs[:type] = new_type
|
46
|
+
slice(field, **kwargs)
|
47
|
+
end
|
48
|
+
|
49
|
+
def transpose_list(key_field="Unkown ID")
|
50
|
+
new_fields = keys.dup
|
51
|
+
new = self.annotate({})
|
52
|
+
TSV.setup(new, :key_field => key_field, :fields => new_fields, :type => type, :filename => filename, :identifiers => identifiers)
|
53
|
+
|
54
|
+
m = Matrix.rows values
|
55
|
+
new_rows = m.transpose.to_a
|
56
|
+
|
57
|
+
fields.zip(new_rows) do |key,row|
|
58
|
+
new[key] = row
|
59
|
+
end
|
60
|
+
|
61
|
+
new
|
62
|
+
end
|
63
|
+
|
64
|
+
def transpose_double(key_field = "Unkown ID")
|
65
|
+
sep = "-!SEP--#{rand 10000}!-"
|
66
|
+
tmp = self.to_list{|v| v * sep}
|
67
|
+
new = tmp.transpose_list(key_field)
|
68
|
+
new.to_double{|v| v.split(sep)}
|
69
|
+
end
|
70
|
+
|
71
|
+
def transpose(key_field = "Unkown ID")
|
72
|
+
case type
|
73
|
+
when :single, :flat
|
74
|
+
self.to_list.transpose_list key_field
|
75
|
+
when :list
|
76
|
+
transpose_list key_field
|
77
|
+
when :double
|
78
|
+
transpose_double key_field
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|