rbbt-util 4.0.2 → 4.1.0
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.
- data/README.rdoc +7 -0
- data/lib/rbbt/annotations.rb +147 -10
- data/lib/rbbt/persist.rb +5 -1
- data/lib/rbbt/persist/tsv.rb +4 -3
- data/lib/rbbt/resource/path.rb +8 -1
- data/lib/rbbt/tsv.rb +3 -2
- data/lib/rbbt/tsv/accessor.rb +140 -51
- data/lib/rbbt/tsv/attach/util.rb +124 -106
- data/lib/rbbt/tsv/filter.rb +4 -2
- data/lib/rbbt/tsv/manipulate.rb +68 -13
- data/lib/rbbt/tsv/parser.rb +110 -20
- data/lib/rbbt/tsv/serializers.rb +6 -0
- data/lib/rbbt/tsv/util.rb +35 -1
- data/lib/rbbt/util/chain_methods.rb +25 -10
- data/lib/rbbt/util/misc.rb +109 -27
- data/lib/rbbt/util/open.rb +15 -4
- data/lib/rbbt/workflow.rb +18 -3
- data/lib/rbbt/workflow/annotate.rb +6 -1
- data/lib/rbbt/workflow/soap.rb +1 -1
- data/lib/rbbt/workflow/step.rb +13 -3
- data/lib/rbbt/workflow/task.rb +2 -2
- data/share/install/software/lib/install_helpers +6 -0
- data/share/lib/R/util.R +6 -1
- data/test/rbbt/test_annotations.rb +7 -0
- data/test/rbbt/test_persist.rb +32 -0
- data/test/rbbt/test_tsv.rb +101 -2
- data/test/rbbt/test_workflow.rb +11 -0
- data/test/rbbt/tsv/test_accessor.rb +15 -0
- data/test/rbbt/tsv/test_attach.rb +1 -1
- data/test/rbbt/tsv/test_manipulate.rb +37 -3
- data/test/rbbt/tsv/test_util.rb +25 -0
- data/test/rbbt/util/test_misc.rb +8 -0
- metadata +7 -4
- data/lib/rbbt/util/persistence.rb +0 -406
data/lib/rbbt/tsv/parser.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rbbt/util/cmd'
|
2
2
|
module TSV
|
3
3
|
class Parser
|
4
|
-
attr_accessor :header_hash, :sep, :sep2, :type, :key_position, :field_positions, :cast, :key_field, :fields, :fix, :select, :serializer, :straight
|
4
|
+
attr_accessor :header_hash, :sep, :sep2, :type, :key_position, :field_positions, :cast, :key_field, :fields, :fix, :select, :serializer, :straight, :take_all, :zipped
|
5
5
|
|
6
6
|
class SKIP_LINE < Exception; end
|
7
7
|
class END_PARSING < Exception; end
|
@@ -63,23 +63,64 @@ module TSV
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def get_values_single(parts)
|
66
|
-
return parts.shift, parts.first if field_positions.nil?
|
66
|
+
return parts.shift, parts.first if field_positions.nil? and key_position.nil?
|
67
67
|
key = parts[key_position]
|
68
|
-
value = parts[field_positions.first]
|
68
|
+
value = parts[field_positions.nil? ? 0 : field_positions.first]
|
69
69
|
[key, value]
|
70
70
|
end
|
71
71
|
|
72
72
|
def get_values_list(parts)
|
73
|
-
return parts.shift, parts if field_positions.nil?
|
73
|
+
return parts.shift, parts if field_positions.nil? and key_position.nil?
|
74
74
|
key = parts[key_position]
|
75
|
-
|
75
|
+
|
76
|
+
values = if field_positions.nil?
|
77
|
+
parts.tap{|o| o.delete_at key_position}
|
78
|
+
else
|
79
|
+
parts.values_at *field_positions
|
80
|
+
end
|
81
|
+
|
76
82
|
[key, values]
|
77
83
|
end
|
78
84
|
|
79
85
|
def get_values_double(parts)
|
80
|
-
return parts.shift.split(@sep2, -1), parts.collect{|value| value.split(@sep2, -1)} if field_positions.nil?
|
86
|
+
return parts.shift.split(@sep2, -1), parts.collect{|value| value.split(@sep2, -1)} if field_positions.nil? and key_position.nil?
|
87
|
+
keys = parts[key_position].split(@sep2, -1)
|
88
|
+
values = if field_positions.nil?
|
89
|
+
parts.tap{|o| o.delete_at key_position}
|
90
|
+
else
|
91
|
+
parts.values_at *field_positions
|
92
|
+
end.collect{|value| value.split(@sep2, -1)}
|
93
|
+
[keys, values]
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_values_flat_inverse(parts)
|
97
|
+
value = parts.shift
|
98
|
+
keys = parts
|
99
|
+
[keys, [value]]
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_values_flat(parts)
|
103
|
+
if key_position and key_position != 0 and field_positions.nil?
|
104
|
+
value = parts.shift
|
105
|
+
keys = parts
|
106
|
+
return [keys, [value]]
|
107
|
+
end
|
108
|
+
|
109
|
+
return parts.shift.split(@sep2, -1), parts.collect{|value| value.split(@sep2, -1)} if
|
110
|
+
field_positions.nil? and (key_position.nil? or key_position == 0)
|
111
|
+
|
81
112
|
keys = parts[key_position].split(@sep2, -1)
|
82
|
-
|
113
|
+
|
114
|
+
if @take_all
|
115
|
+
values = parts.collect{|value| value.split(@sep2, -1)}
|
116
|
+
else
|
117
|
+
|
118
|
+
values = if field_positions.nil?
|
119
|
+
parts.tap{|o| o.delete_at key_position}
|
120
|
+
else
|
121
|
+
parts.values_at *field_positions
|
122
|
+
end.collect{|value| value.split(@sep2, -1)}
|
123
|
+
end
|
83
124
|
[keys, values]
|
84
125
|
end
|
85
126
|
|
@@ -110,18 +151,52 @@ module TSV
|
|
110
151
|
end
|
111
152
|
|
112
153
|
def add_to_data_merge(data, keys, values)
|
113
|
-
keys.each do |key|
|
154
|
+
keys.uniq.each do |key|
|
155
|
+
if data.include? key
|
156
|
+
#data[key] = data[key].zip(values).collect do |old, new|
|
157
|
+
# old.concat new
|
158
|
+
# old
|
159
|
+
#end
|
160
|
+
new = data[key]
|
161
|
+
new.each_with_index do |old, i|
|
162
|
+
old.concat values[i]
|
163
|
+
end
|
164
|
+
data[key] = new
|
165
|
+
else
|
166
|
+
data[key] = values
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def add_to_data_merge_zipped(data, keys, values)
|
172
|
+
num = keys.length
|
173
|
+
values = values.collect{|v| v.length != num ? [v.first] * num : v}
|
174
|
+
all = values.unshift keys
|
175
|
+
Misc.zip_fields(all).each do |values|
|
176
|
+
key = values.shift
|
114
177
|
if data.include? key
|
115
178
|
data[key] = data[key].zip(values).collect do |old, new|
|
116
|
-
old.
|
179
|
+
old.push new
|
117
180
|
old
|
118
181
|
end
|
119
182
|
else
|
120
|
-
data[key] = values
|
183
|
+
data[key] = values.collect{|v| [v]}
|
121
184
|
end
|
122
185
|
end
|
123
186
|
end
|
124
187
|
|
188
|
+
def add_to_data_zipped(data, keys, values)
|
189
|
+
num = keys.length
|
190
|
+
values = values.collect{|v| v.length != num ? [v.first] * num : v}
|
191
|
+
all = values.unshift keys
|
192
|
+
Misc.zip_fields(all).each do |values|
|
193
|
+
key = values.shift
|
194
|
+
next if data.include? key
|
195
|
+
data[key] = values.collect{|v| [v]}
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
|
125
200
|
def cast_values_single(value)
|
126
201
|
case
|
127
202
|
when Symbol === cast
|
@@ -157,6 +232,7 @@ module TSV
|
|
157
232
|
key_field = Misc.process_options options, :key_field
|
158
233
|
fields = Misc.process_options options, :fields
|
159
234
|
|
235
|
+
|
160
236
|
if (key_field.nil? or key_field == 0 or key_field == :key) and
|
161
237
|
(fields.nil? or fields == @fields or (not @fields.nil? and fields == (1..@fields.length).to_a))
|
162
238
|
|
@@ -166,7 +242,7 @@ module TSV
|
|
166
242
|
@straight = false
|
167
243
|
|
168
244
|
case
|
169
|
-
when (key_field.nil? or key_field == @key_field or key_field == 0)
|
245
|
+
when (key_field.nil? or (not Integer === key_field and @key_field.nil?) or key_field == @key_field or key_field == 0)
|
170
246
|
@key_position = 0
|
171
247
|
when Integer === key_field
|
172
248
|
@key_position = key_field
|
@@ -176,9 +252,11 @@ module TSV
|
|
176
252
|
raise "Format of key_field not understood: #{key_field.inspect}"
|
177
253
|
end
|
178
254
|
|
179
|
-
if (fields.nil? or fields == @fields or (not @fields.nil? and fields == (1..@fields.length).to_a))
|
180
|
-
|
181
|
-
|
255
|
+
if (fields.nil? or (not (Array === fields and Integer === fields.first) and @fields.nil?) or fields == @fields or (not @fields.nil? and fields == (1..@fields.length).to_a))
|
256
|
+
if not @fields.nil? and type != :flat
|
257
|
+
@field_positions = (0..@fields.length).to_a
|
258
|
+
@field_positions.delete @key_position
|
259
|
+
end
|
182
260
|
else
|
183
261
|
fields = [fields] if not Array === fields
|
184
262
|
@field_positions = fields.collect{|field|
|
@@ -196,8 +274,12 @@ module TSV
|
|
196
274
|
end
|
197
275
|
|
198
276
|
new_key_field = @fields.dup.unshift(@key_field)[@key_position] if not @fields.nil?
|
199
|
-
@fields = @fields.dup.unshift(@key_field).values_at *@field_positions if not @fields.nil?
|
200
|
-
@
|
277
|
+
@fields = @fields.dup.unshift(@key_field).values_at *@field_positions if not @fields.nil? and not @field_positions.nil?
|
278
|
+
@fields ||= fields if Array === fields and String === fields.first
|
279
|
+
@fields = [@key_field] if new_key_field != @key_field and type == :flat and @field_positions.nil?
|
280
|
+
@key_field = new_key_field
|
281
|
+
@key_field ||= key_field if String === key_field
|
282
|
+
|
201
283
|
end
|
202
284
|
end
|
203
285
|
|
@@ -215,13 +297,19 @@ module TSV
|
|
215
297
|
@type ||= Misc.process_options options, :type
|
216
298
|
@fix = Misc.process_options(options, :fix)
|
217
299
|
@select= Misc.process_options options, :select
|
300
|
+
@zipped = Misc.process_options options, :zipped
|
218
301
|
|
219
302
|
case @type
|
220
303
|
when :double
|
221
304
|
self.instance_eval do alias get_values get_values_double end
|
222
305
|
self.instance_eval do alias cast_values cast_values_double end
|
223
|
-
|
224
|
-
|
306
|
+
case
|
307
|
+
when (merge and not zipped)
|
308
|
+
self.instance_eval do alias add_to_data add_to_data_merge end
|
309
|
+
when (merge and zipped)
|
310
|
+
self.instance_eval do alias add_to_data add_to_data_merge_zipped end
|
311
|
+
when zipped
|
312
|
+
self.instance_eval do alias add_to_data add_to_data_zipped end
|
225
313
|
else
|
226
314
|
self.instance_eval do alias add_to_data add_to_data_no_merge_double end
|
227
315
|
end
|
@@ -234,7 +322,8 @@ module TSV
|
|
234
322
|
self.instance_eval do alias cast_values cast_values_list end
|
235
323
|
self.instance_eval do alias add_to_data add_to_data_no_merge_list end
|
236
324
|
when :flat
|
237
|
-
|
325
|
+
@take_all = true if options[:fields].nil?
|
326
|
+
self.instance_eval do alias get_values get_values_flat end
|
238
327
|
self.instance_eval do alias cast_values cast_values_double end
|
239
328
|
if merge
|
240
329
|
self.instance_eval do alias add_to_data add_to_data_flat_merge end
|
@@ -243,9 +332,10 @@ module TSV
|
|
243
332
|
end
|
244
333
|
end
|
245
334
|
|
335
|
+
fields = options[:fields]
|
246
336
|
fix_fields(options)
|
247
337
|
|
248
|
-
@straight = false if @sep != "\t" or not @cast.nil? or merge
|
338
|
+
@straight = false if @sep != "\t" or not @cast.nil? or merge or (@type == :flat and fields)
|
249
339
|
end
|
250
340
|
|
251
341
|
def setup(data)
|
data/lib/rbbt/tsv/serializers.rb
CHANGED
@@ -14,6 +14,11 @@ module TSV
|
|
14
14
|
def self.load(str); str.unpack("l*"); end
|
15
15
|
end
|
16
16
|
|
17
|
+
class FloatArraySerializer
|
18
|
+
def self.dump(a); a.pack("d*"); end
|
19
|
+
def self.load(str); str.unpack("d*"); end
|
20
|
+
end
|
21
|
+
|
17
22
|
class StringSerializer
|
18
23
|
def self.dump(str); str.to_s; end
|
19
24
|
def self.load(str); str; end
|
@@ -66,6 +71,7 @@ module TSV
|
|
66
71
|
:integer => IntegerSerializer,
|
67
72
|
:float => FloatSerializer,
|
68
73
|
:integer_array => IntegerArraySerializer,
|
74
|
+
:float_array => FloatArraySerializer,
|
69
75
|
:marshal => Marshal,
|
70
76
|
:single => StringSerializer,
|
71
77
|
:string => StringSerializer,
|
data/lib/rbbt/tsv/util.rb
CHANGED
@@ -23,6 +23,38 @@ module TSV
|
|
23
23
|
|
24
24
|
counts
|
25
25
|
end
|
26
|
+
|
27
|
+
def self.field_match_counts(file, values, options = {})
|
28
|
+
options = Misc.add_defaults options, :persist_prefix => "Field_Matches"
|
29
|
+
persist_options = Misc.pull_keys options, :persist
|
30
|
+
|
31
|
+
filename = TSV === file ? file.filename : file
|
32
|
+
text = Persist.persist filename, :string, persist_options do
|
33
|
+
tsv = TSV === file ? file : TSV.open(file)
|
34
|
+
|
35
|
+
text = ""
|
36
|
+
fields = nil
|
37
|
+
tsv.tap{|e| e.unnamed = true; fields = e.fields}.through do |gene, names|
|
38
|
+
names.zip(fields).each do |list, format|
|
39
|
+
list.delete_if do |name| name.empty? end
|
40
|
+
next if list.empty?
|
41
|
+
text << list.collect{|name| [name, format] * "\t"} * "\n" << "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
text
|
45
|
+
end
|
46
|
+
|
47
|
+
path = Persist.persistence_path(filename, persist_options)
|
48
|
+
TmpFile.with_file(values * "\n") do |value_file|
|
49
|
+
cmd = "cat '#{ path }' | grep -w -F -f '#{ value_file }' |cut -f 2 |sort|uniq -c|sed 's/^ *//;s/ /\\t/'"
|
50
|
+
begin
|
51
|
+
TSV.open(CMD.cmd(cmd), :key_field => 1, :type => :single, :cast => :to_i)
|
52
|
+
rescue
|
53
|
+
TSV.setup({nil => 0}, :type => :single, :cast => :to_i)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
26
58
|
def self.get_filename(file)
|
27
59
|
case
|
28
60
|
when String === file
|
@@ -55,7 +87,9 @@ module TSV
|
|
55
87
|
when (field.nil? or field == :key or key_field == field)
|
56
88
|
:key
|
57
89
|
when String === field
|
58
|
-
fields.index field
|
90
|
+
pos = fields.index field
|
91
|
+
Log.medium "Field #{ field } was not found. Options: #{fields * ", "}" if pos.nil?
|
92
|
+
pos
|
59
93
|
end
|
60
94
|
end
|
61
95
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rbbt/util/log'
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
module ChainMethods
|
4
5
|
def self.chain_methods_extended(base)
|
@@ -19,18 +20,31 @@ module ChainMethods
|
|
19
20
|
|
20
21
|
def setup_chains(base)
|
21
22
|
raise "No prefix specified for #{self.to_s}" if self.chain_prefix.nil? or (String === self.chain_prefix and self.chain_prefix.empty?)
|
22
|
-
#methods = self.instance_methods.select{|method| method =~ /^#{self.chain_prefix}/}
|
23
23
|
methods = self.chained_methods
|
24
24
|
|
25
25
|
return if methods.empty?
|
26
26
|
|
27
27
|
prefix = self.chain_prefix
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
#do_chain = true
|
30
|
+
#methods.collect{|new_method|
|
31
|
+
# original = new_method.sub(prefix.to_s + '_', '')
|
32
|
+
# clean = prefix.to_s + '_clean_' + original
|
33
|
+
# if base.respond_to? clean
|
34
|
+
# do_chain = false
|
35
|
+
# break
|
36
|
+
# end
|
37
|
+
#}
|
38
|
+
|
39
|
+
|
40
|
+
if not base.respond_to?(:processed_chains) or base.processed_chains.nil? or not base.processed_chains.include? prefix
|
41
|
+
class << base
|
42
|
+
attr_accessor :processed_chains
|
43
|
+
end if not base.respond_to? :processed_chains
|
44
|
+
|
45
|
+
base.processed_chains = Set.new if base.processed_chains.nil?
|
46
|
+
base.processed_chains << prefix
|
32
47
|
|
33
|
-
if not base.respond_to? first_clean_method
|
34
48
|
class << base; self; end.module_eval do
|
35
49
|
methods.each do |new_method|
|
36
50
|
original = new_method.sub(prefix.to_s + '_', '')
|
@@ -39,6 +53,10 @@ module ChainMethods
|
|
39
53
|
original = "[]" if original == "get_brackets"
|
40
54
|
original = "[]=" if original == "set_brackets"
|
41
55
|
|
56
|
+
if base.respond_to? clean_method
|
57
|
+
raise "Method already defined: #{clean_method}. #{ prefix }"
|
58
|
+
end
|
59
|
+
|
42
60
|
begin
|
43
61
|
alias_method clean_method, original
|
44
62
|
rescue
|
@@ -52,10 +70,10 @@ module ChainMethods
|
|
52
70
|
|
53
71
|
if not metaclass.respond_to? :extended
|
54
72
|
metaclass.module_eval do
|
55
|
-
alias prev_chain_methods_extended extended
|
73
|
+
alias prev_chain_methods_extended extended if methods.include? "extended"
|
56
74
|
|
57
75
|
def extended(base)
|
58
|
-
prev_chain_methods_extended(base)
|
76
|
+
prev_chain_methods_extended(base) if methods.include? "prev_chain_methods_extended"
|
59
77
|
setup_chains(base)
|
60
78
|
end
|
61
79
|
end
|
@@ -68,7 +86,4 @@ module ChainMethods
|
|
68
86
|
def self.extended(base)
|
69
87
|
chain_methods_extended(base)
|
70
88
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
89
|
end
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -2,10 +2,54 @@ require 'lockfile'
|
|
2
2
|
require 'rbbt/util/chain_methods'
|
3
3
|
require 'rbbt/resource/path'
|
4
4
|
require 'rbbt/annotations'
|
5
|
+
require 'net/smtp'
|
5
6
|
|
6
7
|
module Misc
|
7
8
|
class FieldNotFoundError < StandardError;end
|
8
9
|
|
10
|
+
def self.consolidate(list)
|
11
|
+
list.inject(nil){|acc,e|
|
12
|
+
if acc.nil?
|
13
|
+
acc = e
|
14
|
+
else
|
15
|
+
acc.concat e
|
16
|
+
acc
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.positional2hash(keys, *values)
|
22
|
+
if Hash === values.last
|
23
|
+
extra = values.pop
|
24
|
+
inputs = Misc.zip2hash(keys, values)
|
25
|
+
inputs.delete_if{|k,v| v.nil?}
|
26
|
+
inputs = Misc.add_defaults inputs, extra
|
27
|
+
inputs.delete_if{|k,v| not keys.include? k}
|
28
|
+
else
|
29
|
+
Misc.zip2hash(keys, values)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.send_email(from, to, subject, message, options = {})
|
34
|
+
IndiferentHash.setup(options)
|
35
|
+
options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login
|
36
|
+
IndiferentHash.setup(options)
|
37
|
+
|
38
|
+
server, port, user, pass, from_alias, to_alias, auth = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth
|
39
|
+
|
40
|
+
msg = <<-END_OF_MESSAGE
|
41
|
+
From: #{from_alias} <#{from}>
|
42
|
+
To: #{to_alias} <#{to}>
|
43
|
+
Subject: #{subject}
|
44
|
+
|
45
|
+
#{message}
|
46
|
+
END_OF_MESSAGE
|
47
|
+
|
48
|
+
Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
|
49
|
+
smtp.send_message msg, from, to
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
9
53
|
def self.counts(array)
|
10
54
|
counts = Hash.new 0
|
11
55
|
array.each do |e|
|
@@ -13,7 +57,7 @@ module Misc
|
|
13
57
|
end
|
14
58
|
counts
|
15
59
|
end
|
16
|
-
|
60
|
+
|
17
61
|
IUPAC2BASE = {
|
18
62
|
"A" => ["A"],
|
19
63
|
"C" => ["C"],
|
@@ -55,19 +99,16 @@ module Misc
|
|
55
99
|
e1, e2 = a1.shift, a2.shift
|
56
100
|
intersect = []
|
57
101
|
while true
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
else
|
70
|
-
break
|
102
|
+
break if e1.nil? or e2.nil?
|
103
|
+
case e1 <=> e2
|
104
|
+
when 0
|
105
|
+
intersect << e1
|
106
|
+
e1, e2 = a1.shift, a2.shift
|
107
|
+
when -1
|
108
|
+
e1 = a1.shift while not e1.nil? and e1 < e2
|
109
|
+
when 1
|
110
|
+
e2 = a2.shift
|
111
|
+
e2 = a2.shift while not e2.nil? and e2 < e1
|
71
112
|
end
|
72
113
|
end
|
73
114
|
intersect
|
@@ -167,6 +208,22 @@ module Misc
|
|
167
208
|
res
|
168
209
|
end
|
169
210
|
|
211
|
+
def self.memprof
|
212
|
+
require 'memprof'
|
213
|
+
Memprof.start
|
214
|
+
begin
|
215
|
+
res = yield
|
216
|
+
rescue Exception
|
217
|
+
puts "Profiling aborted"
|
218
|
+
raise $!
|
219
|
+
ensure
|
220
|
+
Memprof.stop
|
221
|
+
print Memprof.stats
|
222
|
+
end
|
223
|
+
|
224
|
+
res
|
225
|
+
end
|
226
|
+
|
170
227
|
def self.insist(times = 3)
|
171
228
|
try = 0
|
172
229
|
begin
|
@@ -228,6 +285,8 @@ module Misc
|
|
228
285
|
FileUtils.mkdir_p dir unless File.exists? dir
|
229
286
|
FileUtils.cd dir
|
230
287
|
res = yield
|
288
|
+
rescue
|
289
|
+
raise $!
|
231
290
|
ensure
|
232
291
|
FileUtils.cd old_pwd
|
233
292
|
end
|
@@ -271,8 +330,9 @@ module Misc
|
|
271
330
|
else
|
272
331
|
raise "Format of '#{options.inspect}' not understood. It should be a hash"
|
273
332
|
end
|
333
|
+
|
274
334
|
defaults.each do |key, value|
|
275
|
-
next
|
335
|
+
next if options.include? key
|
276
336
|
|
277
337
|
new_options[key] = value
|
278
338
|
end
|
@@ -419,12 +479,15 @@ end
|
|
419
479
|
|
420
480
|
module NamedArray
|
421
481
|
extend ChainMethods
|
482
|
+
|
422
483
|
self.chain_prefix = :named_array
|
423
484
|
attr_accessor :fields
|
485
|
+
attr_accessor :key
|
424
486
|
|
425
|
-
def self.setup(array, fields)
|
487
|
+
def self.setup(array, fields, key = nil)
|
426
488
|
array.extend NamedArray
|
427
489
|
array.fields = fields
|
490
|
+
array.key = key
|
428
491
|
array
|
429
492
|
end
|
430
493
|
|
@@ -455,11 +518,13 @@ module NamedArray
|
|
455
518
|
if defined? Entity
|
456
519
|
entity = (defined?(Entity) and Entity.respond_to?(:formats)) ? Entity.formats[key] : nil
|
457
520
|
if entity
|
458
|
-
if entity.annotations.first == :format
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
521
|
+
elem = if entity.annotations.first == :format
|
522
|
+
entity.setup(named_array_clean_get_brackets(Misc.field_position(fields, key)), key)
|
523
|
+
else
|
524
|
+
entity.setup(named_array_clean_get_brackets(Misc.field_position(fields, key)))
|
525
|
+
end
|
526
|
+
elem.context = self
|
527
|
+
elem
|
463
528
|
else
|
464
529
|
named_array_clean_get_brackets(Misc.field_position(fields, key))
|
465
530
|
end
|
@@ -469,18 +534,21 @@ module NamedArray
|
|
469
534
|
end
|
470
535
|
|
471
536
|
def named_array_each(&block)
|
472
|
-
if defined?(Entity) and not fields.nil? and not fields.empty?
|
473
|
-
fields.zip(self) do |field,elem|
|
537
|
+
if defined?(Entity) and not @fields.nil? and not @fields.empty?
|
538
|
+
@fields.zip(self).each do |field,elem|
|
474
539
|
entity = (defined?(Entity) and Entity.respond_to?(:formats)) ? Entity.formats[field] : nil
|
540
|
+
|
475
541
|
if entity
|
476
542
|
elem = elem.dup if elem.frozen?
|
477
543
|
if entity.annotations.first == :format
|
478
|
-
|
544
|
+
entity.setup(elem, field)
|
479
545
|
else
|
480
|
-
|
546
|
+
entity.setup(elem)
|
481
547
|
end
|
482
|
-
|
548
|
+
elem.context = self
|
549
|
+
elem
|
483
550
|
end
|
551
|
+
|
484
552
|
yield(elem)
|
485
553
|
elem
|
486
554
|
end
|
@@ -489,6 +557,20 @@ module NamedArray
|
|
489
557
|
end
|
490
558
|
end
|
491
559
|
|
560
|
+
def named_array_collect
|
561
|
+
res = []
|
562
|
+
|
563
|
+
named_array_each do |elem|
|
564
|
+
if block_given?
|
565
|
+
res << yield(elem)
|
566
|
+
else
|
567
|
+
res << elem
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
res
|
572
|
+
end
|
573
|
+
|
492
574
|
def named_array_set_brackets(key,value)
|
493
575
|
named_array_clean_set_brackets(Misc.field_position(fields, key), value)
|
494
576
|
end
|
@@ -517,7 +599,7 @@ module NamedArray
|
|
517
599
|
|
518
600
|
def report
|
519
601
|
fields.zip(self).collect do |field,value|
|
520
|
-
"
|
602
|
+
"#{ field }: #{ Array === value ? value * "|" : value }"
|
521
603
|
end * "\n"
|
522
604
|
end
|
523
605
|
|