rbbt-util 4.2.0 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rbbt/annotations.rb +46 -18
- data/lib/rbbt/persist.rb +75 -5
- data/lib/rbbt/persist/tsv.rb +54 -10
- data/lib/rbbt/resource.rb +28 -19
- data/lib/rbbt/resource/path.rb +12 -5
- data/lib/rbbt/tsv/accessor.rb +8 -2
- data/lib/rbbt/tsv/parser.rb +1 -0
- data/lib/rbbt/tsv/util.rb +1 -0
- data/lib/rbbt/util/cmd.rb +7 -3
- data/lib/rbbt/util/log.rb +24 -13
- data/lib/rbbt/util/misc.rb +126 -19
- data/lib/rbbt/util/open.rb +1 -3
- data/lib/rbbt/workflow.rb +1 -1
- data/lib/rbbt/workflow/accessor.rb +15 -4
- data/lib/rbbt/workflow/step.rb +23 -12
- data/test/rbbt/resource/test_path.rb +12 -0
- data/test/rbbt/test_persist.rb +46 -0
- data/test/rbbt/tsv/test_index.rb +1 -1
- data/test/rbbt/util/test_misc.rb +12 -1
- metadata +19 -7
data/lib/rbbt/annotations.rb
CHANGED
@@ -13,6 +13,7 @@ module Annotated
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def annotations
|
16
|
+
raise "Annotation types is nil for object: #{self.inspect}" if annotation_types.nil?
|
16
17
|
annotation_types.collect do |mod|
|
17
18
|
mod.annotations
|
18
19
|
end.flatten.uniq
|
@@ -32,9 +33,11 @@ module Annotated
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def self.load(object, info)
|
35
|
-
annotation_types = info[:annotation_types]
|
36
|
+
annotation_types = info[:annotation_types] || []
|
36
37
|
annotation_types = annotation_types.split("+") if String === annotation_types
|
37
38
|
|
39
|
+
return object if annotation_types.nil? or annotation_types.empty?
|
40
|
+
|
38
41
|
annotation_types.each do |mod|
|
39
42
|
mod = Misc.string2const(mod) if String === mod
|
40
43
|
mod.setup(object, *info.values_at(*mod.all_annotations))
|
@@ -59,10 +62,8 @@ module Annotated
|
|
59
62
|
info.to_json
|
60
63
|
when field == "annotation_types"
|
61
64
|
annotation_types.collect{|t| t.to_s} * "+"
|
62
|
-
when field == "literal array"
|
63
|
-
(self * "|").gsub(/\n|\t/, ' ')
|
64
65
|
when field == "literal"
|
65
|
-
self.gsub(/\n|\t/, ' ')
|
66
|
+
(Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
|
66
67
|
when info.include?(field.to_sym)
|
67
68
|
info.delete(field.to_sym)
|
68
69
|
when self.respond_to?(field)
|
@@ -78,17 +79,16 @@ module Annotated
|
|
78
79
|
fields = fields.flatten
|
79
80
|
info = {}
|
80
81
|
literal_pos = fields.index "literal"
|
81
|
-
literal_array_pos = fields.index "literal array"
|
82
82
|
|
83
83
|
object = case
|
84
84
|
when literal_pos
|
85
85
|
values[literal_pos]
|
86
|
-
when literal_array_pos
|
87
|
-
values[literal_array_pos].split("|").extend AnnotatedArray
|
88
86
|
else
|
89
87
|
id.dup
|
90
88
|
end
|
91
89
|
|
90
|
+
object = object["Array:".length..-1].split("|") if object =~ /^Array:/
|
91
|
+
|
92
92
|
if Array === values
|
93
93
|
Misc.zip_fields(values).collect do |list|
|
94
94
|
fields.each_with_index do |field,i|
|
@@ -120,23 +120,23 @@ module Annotated
|
|
120
120
|
return nil if annotations.nil?
|
121
121
|
fields = case
|
122
122
|
when ((fields.compact.empty?) and not annotations.empty?)
|
123
|
-
fields = AnnotatedArray === annotations ? annotations.annotations : annotations.first.annotations
|
123
|
+
fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
|
124
124
|
fields << :annotation_types
|
125
125
|
when (fields == [:literal] and not annotations.empty?)
|
126
126
|
fields << :literal
|
127
127
|
when (fields == [:all] and not annotations.empty?)
|
128
|
-
fields = [:annotation_types] + (Annotated === annotations ? annotations.annotations : annotations.first.annotations)
|
128
|
+
fields = [:annotation_types] + (Annotated === annotations ? annotations.annotations : annotations.compact.first.annotations)
|
129
129
|
fields << :literal
|
130
|
+
when annotations.empty?
|
131
|
+
[:annotation_types, :literal]
|
130
132
|
else
|
131
133
|
fields.flatten
|
132
134
|
end
|
133
135
|
|
134
136
|
fields = fields.collect{|f| f.to_s}
|
135
137
|
|
136
|
-
fields = fields.collect{|f| ((f == "literal" and AnnotatedArray === annotations) ? "literal array" : f)}
|
137
|
-
|
138
138
|
case
|
139
|
-
when (Annotated === annotations and not annotations.double_array)
|
139
|
+
when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
|
140
140
|
tsv = TSV.setup({}, :key_field => "Single", :fields => fields, :type => :list, :unnamed => true)
|
141
141
|
tsv[annotations.id] = annotations.tsv_values(*fields)
|
142
142
|
when Array === annotations
|
@@ -157,10 +157,11 @@ module Annotated
|
|
157
157
|
Annotated.load_tsv_values(id, values, tsv.fields)
|
158
158
|
end
|
159
159
|
|
160
|
-
|
160
|
+
case tsv.key_field
|
161
|
+
when "Single"
|
161
162
|
annotated_entities.first
|
162
163
|
else
|
163
|
-
annotated_entities
|
164
|
+
annotated_entities
|
164
165
|
end
|
165
166
|
end
|
166
167
|
end
|
@@ -260,10 +261,11 @@ end
|
|
260
261
|
|
261
262
|
module AnnotatedArray
|
262
263
|
extend ChainMethods
|
264
|
+
|
263
265
|
self.chain_prefix = :annotated_array
|
264
266
|
|
265
267
|
def double_array
|
266
|
-
AnnotatedArray === self.
|
268
|
+
AnnotatedArray === self.annotated_array_clean_get_brackets(0)
|
267
269
|
end
|
268
270
|
|
269
271
|
def annotated_array_first
|
@@ -276,6 +278,7 @@ module AnnotatedArray
|
|
276
278
|
|
277
279
|
def annotated_array_get_brackets(pos)
|
278
280
|
value = annotated_array_clean_get_brackets(pos)
|
281
|
+
value = value.dup if value.frozen?
|
279
282
|
annotation_types.each do |mod|
|
280
283
|
mod.setup(value, *info.values_at(*mod.all_annotations))
|
281
284
|
end
|
@@ -303,8 +306,14 @@ module AnnotatedArray
|
|
303
306
|
def annotated_array_collect
|
304
307
|
res = []
|
305
308
|
|
306
|
-
|
307
|
-
|
309
|
+
if block_given?
|
310
|
+
annotated_array_each do |value|
|
311
|
+
res << yield(value)
|
312
|
+
end
|
313
|
+
else
|
314
|
+
annotated_array_each do |value|
|
315
|
+
res << value
|
316
|
+
end
|
308
317
|
end
|
309
318
|
|
310
319
|
res
|
@@ -352,11 +361,14 @@ module AnnotatedArray
|
|
352
361
|
|
353
362
|
def annotated_array_remove(list)
|
354
363
|
value = (self - list)
|
364
|
+
|
355
365
|
annotation_types.each do |mod|
|
356
366
|
mod.setup(value, *info.values_at(*mod.annotations))
|
357
367
|
end
|
368
|
+
|
358
369
|
value.context = self.context
|
359
370
|
value.container = self.container
|
371
|
+
|
360
372
|
value
|
361
373
|
end
|
362
374
|
|
@@ -369,6 +381,7 @@ module AnnotatedArray
|
|
369
381
|
|
370
382
|
value.context = self.context
|
371
383
|
value.container = self.container
|
384
|
+
|
372
385
|
value
|
373
386
|
end
|
374
387
|
|
@@ -381,8 +394,10 @@ module AnnotatedArray
|
|
381
394
|
|
382
395
|
value.context = self.context
|
383
396
|
value.container = self.container
|
397
|
+
|
384
398
|
value
|
385
399
|
end
|
400
|
+
|
386
401
|
def annotated_array_flatten
|
387
402
|
value = self.annotated_array_clean_flatten.dup
|
388
403
|
|
@@ -392,27 +407,33 @@ module AnnotatedArray
|
|
392
407
|
|
393
408
|
value.context = self.context
|
394
409
|
value.container = self.container
|
410
|
+
|
395
411
|
value
|
396
412
|
end
|
397
413
|
|
398
414
|
def annotated_array_reverse
|
399
415
|
value = self.annotated_array_clean_reverse
|
416
|
+
|
400
417
|
annotation_types.each do |mod|
|
401
418
|
mod.setup(value, *info.values_at(*mod.annotations))
|
402
419
|
end
|
420
|
+
|
403
421
|
value.context = self.context
|
404
422
|
value.container = self.container
|
423
|
+
|
405
424
|
value
|
406
425
|
end
|
407
426
|
|
408
|
-
|
409
427
|
def annotated_array_sort_by(&block)
|
410
428
|
value = self.annotated_array_clean_sort_by &block
|
429
|
+
|
411
430
|
annotation_types.each do |mod|
|
412
431
|
mod.setup(value, *info.values_at(*mod.annotations))
|
413
432
|
end
|
433
|
+
|
414
434
|
value.context = self.context
|
415
435
|
value.container = self.container
|
436
|
+
|
416
437
|
value
|
417
438
|
end
|
418
439
|
|
@@ -422,8 +443,10 @@ module AnnotatedArray
|
|
422
443
|
annotation_types.each do |mod|
|
423
444
|
mod.setup(value, *info.values_at(*mod.annotations))
|
424
445
|
end
|
446
|
+
|
425
447
|
value.context = self.context
|
426
448
|
value.container = self.container
|
449
|
+
|
427
450
|
value
|
428
451
|
end
|
429
452
|
|
@@ -445,4 +468,9 @@ module AnnotatedArray
|
|
445
468
|
|
446
469
|
value
|
447
470
|
end
|
471
|
+
|
472
|
+
def self.annotate(list)
|
473
|
+
list[0].annotate list unless AnnotatedArray === list or list[0].nil? or (not list[0].respond_to? :annotate)
|
474
|
+
end
|
475
|
+
|
448
476
|
end
|
data/lib/rbbt/persist.rb
CHANGED
@@ -155,9 +155,72 @@ module Persist
|
|
155
155
|
if persist_options[:persist]
|
156
156
|
path = persistence_path(name, persist_options, other_options || {})
|
157
157
|
|
158
|
-
case
|
159
|
-
when :memory
|
158
|
+
case
|
159
|
+
when type.to_sym === :memory
|
160
160
|
Persist::MEMORY[path] ||= yield
|
161
|
+
|
162
|
+
when (type.to_sym == :annotations and persist_options.include? :annotation_repo)
|
163
|
+
|
164
|
+
repo = persist_options[:annotation_repo]
|
165
|
+
|
166
|
+
keys = nil
|
167
|
+
subkey = name + ":"
|
168
|
+
|
169
|
+
if String === repo
|
170
|
+
repo = Persist.open_tokyocabinet(repo, false, :list, "BDB")
|
171
|
+
repo.read_and_close do
|
172
|
+
keys = repo.range subkey + 0.chr, true, subkey + 254.chr, true
|
173
|
+
end
|
174
|
+
repo.close
|
175
|
+
else
|
176
|
+
repo.read_and_close do
|
177
|
+
keys = repo.range subkey + 0.chr, true, subkey + 254.chr, true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
case
|
182
|
+
when (keys.length == 1 and keys.first == subkey + 'NIL')
|
183
|
+
nil
|
184
|
+
when (keys.length == 1 and keys.first == subkey + 'EMPTY')
|
185
|
+
[]
|
186
|
+
when (keys.length == 1 and keys.first =~ /:SINGLE$/)
|
187
|
+
key = keys.first
|
188
|
+
values = repo.write_and_close do
|
189
|
+
repo[key]
|
190
|
+
end
|
191
|
+
Annotated.load_tsv_values(key, values, "literal", "annotation_types", "JSON")
|
192
|
+
when keys.any?
|
193
|
+
repo.read_and_close do
|
194
|
+
keys.collect{|key|
|
195
|
+
v = repo[key]
|
196
|
+
Annotated.load_tsv_values(key, v, "literal", "annotation_types", "JSON")
|
197
|
+
}
|
198
|
+
end
|
199
|
+
else
|
200
|
+
entities = yield
|
201
|
+
|
202
|
+
Misc.lock(repo.persistence_path) do
|
203
|
+
repo.write_and_close do
|
204
|
+
case
|
205
|
+
when entities.nil?
|
206
|
+
repo[subkey + "NIL"] = nil
|
207
|
+
when entities.empty?
|
208
|
+
repo[subkey + "EMPTY"] = nil
|
209
|
+
when (not Array === entities or AnnotatedArray === entities)
|
210
|
+
tsv_values = entities.tsv_values("literal", "annotation_types", "JSON")
|
211
|
+
repo[subkey + entities.id << ":" << "SINGLE"] = tsv_values
|
212
|
+
else
|
213
|
+
entities.each do |e|
|
214
|
+
tsv_values = e.tsv_values("literal", "annotation_types", "JSON")
|
215
|
+
repo[subkey + e.id] = tsv_values
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
entities
|
222
|
+
end
|
223
|
+
|
161
224
|
else
|
162
225
|
Misc.lock(path) do
|
163
226
|
if is_persisted?(path, persist_options)
|
@@ -167,11 +230,18 @@ module Persist
|
|
167
230
|
else
|
168
231
|
Log.debug "Persist create: #{ path } - #{persist_options.inspect[0..100]}"
|
169
232
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
233
|
+
begin
|
234
|
+
res = yield
|
235
|
+
save_file(path, type, res)
|
236
|
+
res
|
237
|
+
rescue
|
238
|
+
Log.high "Error in persist. Erasing '#{ path }'"
|
239
|
+
FileUtils.rm path if File.exists? path
|
240
|
+
raise $!
|
241
|
+
end
|
173
242
|
end
|
174
243
|
end
|
244
|
+
|
175
245
|
else
|
176
246
|
yield
|
177
247
|
end
|
data/lib/rbbt/persist/tsv.rb
CHANGED
@@ -2,13 +2,18 @@ require 'tokyocabinet'
|
|
2
2
|
|
3
3
|
module Persist
|
4
4
|
TC_CONNECTIONS = {}
|
5
|
-
|
5
|
+
|
6
|
+
def self.open_tokyocabinet(path, write, serializer = nil, tokyocabinet_class = TokyoCabinet::HDB)
|
6
7
|
write = true if not File.exists?(path)
|
7
|
-
|
8
|
+
|
9
|
+
tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB"
|
10
|
+
tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
|
11
|
+
|
12
|
+
flags = (write ? tokyocabinet_class::OWRITER | tokyocabinet_class::OCREAT : tokyocabinet_class::OREADER)
|
8
13
|
|
9
14
|
FileUtils.mkdir_p File.dirname(path) unless File.exists?(File.dirname(path))
|
10
15
|
|
11
|
-
database = TC_CONNECTIONS[path] ||=
|
16
|
+
database = TC_CONNECTIONS[path] ||= tokyocabinet_class.new
|
12
17
|
database.close
|
13
18
|
|
14
19
|
if !database.open(path, flags)
|
@@ -18,7 +23,11 @@ module Persist
|
|
18
23
|
|
19
24
|
if not database.respond_to? :old_close
|
20
25
|
class << database
|
21
|
-
attr_accessor :writable, :closed, :persistence_path
|
26
|
+
attr_accessor :writable, :closed, :persistence_path, :tokyocabinet_class
|
27
|
+
|
28
|
+
def closed?
|
29
|
+
@closed
|
30
|
+
end
|
22
31
|
|
23
32
|
alias old_close close
|
24
33
|
def close
|
@@ -29,7 +38,7 @@ module Persist
|
|
29
38
|
def read(force = false)
|
30
39
|
return if not write? and not closed and not force
|
31
40
|
self.close
|
32
|
-
if !self.open(@persistence_path,
|
41
|
+
if !self.open(@persistence_path, tokyocabinet_class::OREADER)
|
33
42
|
ecode = self.ecode
|
34
43
|
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
35
44
|
end
|
@@ -41,10 +50,12 @@ module Persist
|
|
41
50
|
def write(force = true)
|
42
51
|
return if write? and not closed and not force
|
43
52
|
self.close
|
44
|
-
|
53
|
+
|
54
|
+
if !self.open(@persistence_path, tokyocabinet_class::OWRITER)
|
45
55
|
ecode = self.ecode
|
46
56
|
raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
|
47
57
|
end
|
58
|
+
|
48
59
|
@writable = true
|
49
60
|
@closed = false
|
50
61
|
self
|
@@ -70,6 +81,19 @@ module Persist
|
|
70
81
|
out(key)
|
71
82
|
end
|
72
83
|
|
84
|
+
def write_and_close
|
85
|
+
write if @closed or not write?
|
86
|
+
res = yield
|
87
|
+
close
|
88
|
+
res
|
89
|
+
end
|
90
|
+
|
91
|
+
def read_and_close
|
92
|
+
read if @closed or write?
|
93
|
+
res = yield
|
94
|
+
close
|
95
|
+
res
|
96
|
+
end
|
73
97
|
|
74
98
|
def merge!(hash)
|
75
99
|
hash.each do |key,values|
|
@@ -77,10 +101,19 @@ module Persist
|
|
77
101
|
end
|
78
102
|
end
|
79
103
|
|
104
|
+
if instance_methods.include? "range"
|
105
|
+
alias old_range range
|
106
|
+
|
107
|
+
def range(*args)
|
108
|
+
keys = old_range(*args)
|
109
|
+
keys - TSV::ENTRY_KEYS
|
110
|
+
end
|
111
|
+
end
|
80
112
|
end
|
81
113
|
end
|
82
114
|
|
83
115
|
database.persistence_path ||= path
|
116
|
+
database.tokyocabinet_class = tokyocabinet_class
|
84
117
|
|
85
118
|
TSV.setup database
|
86
119
|
database.serializer = serializer || database.serializer
|
@@ -103,7 +136,7 @@ module Persist
|
|
103
136
|
|
104
137
|
if is_persisted? path
|
105
138
|
Log.debug "TSV persistence up-to-date: #{ path }"
|
106
|
-
return open_tokyocabinet(path, false)
|
139
|
+
return Misc.lock(path) do open_tokyocabinet(path, false); end
|
107
140
|
else
|
108
141
|
Log.debug "TSV persistence creating: #{ path }"
|
109
142
|
end
|
@@ -112,13 +145,24 @@ module Persist
|
|
112
145
|
|
113
146
|
data = open_tokyocabinet(path, true, persist_options[:serializer])
|
114
147
|
data.serializer = :type unless data.serializer
|
148
|
+
|
149
|
+
data.close
|
150
|
+
|
115
151
|
data
|
116
152
|
else
|
117
|
-
|
153
|
+
{}
|
118
154
|
end
|
119
155
|
|
120
156
|
begin
|
121
|
-
|
157
|
+
if data.respond_to? :persistence_path and data != persist_options[:data]
|
158
|
+
Misc.lock data.persistence_path do
|
159
|
+
data.write_and_close do
|
160
|
+
yield data
|
161
|
+
end
|
162
|
+
end
|
163
|
+
else
|
164
|
+
yield data
|
165
|
+
end
|
122
166
|
rescue Exception
|
123
167
|
begin
|
124
168
|
data.close if data.respondo_to? :close
|
@@ -128,7 +172,7 @@ module Persist
|
|
128
172
|
raise $!
|
129
173
|
end
|
130
174
|
|
131
|
-
data.read if data.respond_to? :read and
|
175
|
+
data.read if data.respond_to? :read and ((data.respond_to?(:write?) and data.write?) or (data.respond_to?(:closed?) and data.closed?))
|
132
176
|
|
133
177
|
data
|
134
178
|
end
|
data/lib/rbbt/resource.rb
CHANGED
@@ -66,33 +66,42 @@ module Resource
|
|
66
66
|
raise "Resource #{ path } does not seem to be claimed"
|
67
67
|
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
69
|
+
if not File.exists? path
|
70
|
+
Misc.lock path + '.produce' do
|
71
|
+
begin
|
72
|
+
case type
|
73
|
+
when :string
|
74
|
+
Open.write(path, content)
|
75
|
+
when :url
|
76
|
+
Open.write(path, Open.open(content))
|
77
|
+
when :proc
|
78
|
+
data = content.call
|
79
|
+
Open.write(path, data)
|
80
|
+
when :rake
|
81
|
+
run_rake(path, content, rake_dir)
|
82
|
+
when :install
|
83
|
+
Log.debug "Installing software: #{path}"
|
84
|
+
software_dir = path.resource.root.software.find :user
|
85
|
+
preamble = <<-EOF
|
83
86
|
#!/bin/bash
|
84
87
|
|
85
88
|
RBBT_SOFTWARE_DIR="#{software_dir}"
|
86
89
|
|
87
90
|
INSTALL_HELPER_FILE="#{Rbbt.share.install.software.lib.install_helpers.find :lib, caller_lib_dir(__FILE__)}"
|
88
91
|
source "$INSTALL_HELPER_FILE"
|
89
|
-
|
92
|
+
EOF
|
90
93
|
|
91
|
-
|
94
|
+
CMD.cmd('bash', :in => preamble + "\n" + Open.read(content))
|
92
95
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
+
set_software_env(software_dir)
|
97
|
+
else
|
98
|
+
raise "Could not produce #{ resource }. (#{ type }, #{ content })"
|
99
|
+
end
|
100
|
+
rescue
|
101
|
+
FileUtils.rm path if File.exists? path
|
102
|
+
raise $!
|
103
|
+
end
|
104
|
+
end
|
96
105
|
end
|
97
106
|
|
98
107
|
path
|
data/lib/rbbt/resource/path.rb
CHANGED
@@ -59,9 +59,12 @@ module Path
|
|
59
59
|
:global => File.join('/', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
60
60
|
:local => File.join('/usr/local', "{TOPLEVEL}", "{PKGDIR}", "{SUBPATH}"),
|
61
61
|
:lib => File.join('{LIBDIR}', "{TOPLEVEL}", "{SUBPATH}"),
|
62
|
+
:default => :user
|
62
63
|
}
|
63
64
|
|
64
|
-
def find(where = nil, caller_lib = nil)
|
65
|
+
def find(where = nil, caller_lib = nil, search_paths = nil)
|
66
|
+
where = search_paths[:default] if where == :default
|
67
|
+
search_paths ||= SEARCH_PATHS
|
65
68
|
return self if located?
|
66
69
|
if self.match(/(.*?)\/(.*)/)
|
67
70
|
toplevel, subpath = self.match(/(.*?)\/(.*)/).values_at 1, 2
|
@@ -71,15 +74,19 @@ module Path
|
|
71
74
|
|
72
75
|
path = nil
|
73
76
|
if where.nil?
|
74
|
-
|
75
|
-
path = find(w, caller_lib)
|
77
|
+
search_paths.keys.each do |w|
|
78
|
+
path = find(w, caller_lib, search_paths)
|
76
79
|
return path if File.exists? path
|
77
80
|
end
|
78
|
-
|
81
|
+
if search_paths.include? :default
|
82
|
+
find((search_paths[:default] || :user), caller_lib, search_paths)
|
83
|
+
else
|
84
|
+
raise "Path '#{ path }' not found, and no default specified in search paths: #{search_paths.inspect}"
|
85
|
+
end
|
79
86
|
else
|
80
87
|
libdir = where == :lib ? Path.caller_lib_dir(caller_lib) : ""
|
81
88
|
libdir ||= ""
|
82
|
-
Path.setup
|
89
|
+
Path.setup search_paths[where].sub('{PKGDIR}', pkgdir).sub('{TOPLEVEL}', toplevel).sub('{SUBPATH}', subpath).sub('{LIBDIR}', libdir), @pkgdir, @resource
|
83
90
|
end
|
84
91
|
end
|
85
92
|
|
data/lib/rbbt/tsv/accessor.rb
CHANGED
@@ -306,11 +306,17 @@ if '#{entry}' == 'serializer'
|
|
306
306
|
|
307
307
|
define_method :serialized_get do |key|
|
308
308
|
return nil unless self.include? key
|
309
|
-
|
309
|
+
res = tsv_clean_get_brackets(key)
|
310
|
+
return res if res.nil?
|
311
|
+
self.serializer_module.load(res)
|
310
312
|
end
|
311
313
|
|
312
314
|
define_method :serialized_set do |key, value|
|
313
|
-
|
315
|
+
if value.nil?
|
316
|
+
tsv_clean_set_brackets key, value
|
317
|
+
else
|
318
|
+
tsv_clean_set_brackets key, self.serializer_module.dump(value)
|
319
|
+
end
|
314
320
|
end
|
315
321
|
end
|
316
322
|
end
|
data/lib/rbbt/tsv/parser.rb
CHANGED
@@ -258,6 +258,7 @@ module TSV
|
|
258
258
|
@key_position = key_field
|
259
259
|
when String === key_field
|
260
260
|
@key_position = @fields.dup.unshift(@key_field).index key_field
|
261
|
+
raise "Key field #{ key_field } was not found" if @key_position.nil?
|
261
262
|
else
|
262
263
|
raise "Format of key_field not understood: #{key_field.inspect}"
|
263
264
|
end
|
data/lib/rbbt/tsv/util.rb
CHANGED
@@ -87,6 +87,7 @@ module TSV
|
|
87
87
|
when (field.nil? or field == :key or key_field == field)
|
88
88
|
:key
|
89
89
|
when String === field
|
90
|
+
raise "No fields specified in TSV.identify_field" if fields.nil?
|
90
91
|
pos = fields.index field
|
91
92
|
Log.medium "Field #{ field } was not found. Options: #{fields * ", "}" if pos.nil?
|
92
93
|
pos
|
data/lib/rbbt/util/cmd.rb
CHANGED
@@ -54,13 +54,17 @@ module CMD
|
|
54
54
|
def force_close
|
55
55
|
if @pid
|
56
56
|
Log.debug "Forcing close by killing '#{@pid}'" if log
|
57
|
-
|
58
|
-
|
57
|
+
begin
|
58
|
+
Process.kill("KILL", @pid)
|
59
|
+
Process.waitpid(@pid)
|
60
|
+
rescue
|
61
|
+
Log.low "Exception in forcing close of command [#{ @pid }, #{cmd}]: #{$!.message}"
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
@post.call if @post
|
62
66
|
|
63
|
-
original_close
|
67
|
+
original_close unless self.closed?
|
64
68
|
end
|
65
69
|
|
66
70
|
def read(*args)
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -8,14 +8,23 @@ module Log
|
|
8
8
|
WARN = 5
|
9
9
|
ERROR = 6
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
class << self
|
12
|
+
attr_accessor :logfile, :severity
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
|
16
|
+
def self.logfile
|
17
|
+
@logfile = nil
|
17
18
|
end
|
18
19
|
|
20
|
+
#def self.severity=(severity)
|
21
|
+
# @severity = severity
|
22
|
+
#end
|
23
|
+
|
24
|
+
#def self.severity
|
25
|
+
# @severity
|
26
|
+
#end
|
27
|
+
|
19
28
|
SEVERITY_COLOR = ["0;37m", "0;32m", "0;33m", "0;31m", "1;0m" ].collect{|e| "\033[#{e}"}
|
20
29
|
|
21
30
|
def self.log(message, severity = MEDIUM)
|
@@ -23,9 +32,11 @@ module Log
|
|
23
32
|
severity_color = SEVERITY_COLOR[severity]
|
24
33
|
font_color = {false => "\033[0;37m", true => "\033[0m"}[severity >= INFO]
|
25
34
|
|
26
|
-
|
27
|
-
|
28
|
-
|
35
|
+
if severity >= self.severity and not message.empty?
|
36
|
+
str = "\033[0;37m#{Time.now.strftime("[%m/%d/%y-%H:%M:%S]")}#{severity_color}[#{severity.to_s}]\033[0m:#{font_color} " << message.strip << "\033[0m"
|
37
|
+
STDERR.puts str
|
38
|
+
logfile.puts str unless logfile.nil?
|
39
|
+
end
|
29
40
|
end
|
30
41
|
|
31
42
|
def self.debug(message)
|
@@ -59,17 +70,17 @@ module Log
|
|
59
70
|
|
60
71
|
case ENV['RBBT_LOG']
|
61
72
|
when 'DEBUG'
|
62
|
-
|
73
|
+
self.severity = DEBUG
|
63
74
|
when 'LOW'
|
64
|
-
|
75
|
+
self.severity = LOW
|
65
76
|
when 'MEDIUM'
|
66
|
-
|
77
|
+
self.severity = MEDIUM
|
67
78
|
when 'HIGH'
|
68
|
-
|
79
|
+
self.severity = HIGH
|
69
80
|
when nil
|
70
|
-
|
81
|
+
self.severity = INFO
|
71
82
|
else
|
72
|
-
|
83
|
+
self.severity = ENV['RBBT_LOG'].to_i
|
73
84
|
end
|
74
85
|
end
|
75
86
|
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -3,10 +3,34 @@ require 'rbbt/util/chain_methods'
|
|
3
3
|
require 'rbbt/resource/path'
|
4
4
|
require 'rbbt/annotations'
|
5
5
|
require 'net/smtp'
|
6
|
+
require 'narray'
|
6
7
|
|
7
8
|
module Misc
|
8
9
|
class FieldNotFoundError < StandardError;end
|
9
10
|
|
11
|
+
ARRAY_MAX_LENGTH = 10000
|
12
|
+
STRING_MAX_LENGTH = ARRAY_MAX_LENGTH * 10
|
13
|
+
def self.remove_long_items(obj)
|
14
|
+
case
|
15
|
+
when (Array === obj and obj.length > ARRAY_MAX_LENGTH)
|
16
|
+
remove_long_items(obj[0..ARRAY_MAX_LENGTH-2] << "TRUNCATED at #{ ARRAY_MAX_LENGTH } (#{obj.length})")
|
17
|
+
when (Hash === obj and obj.length > ARRAY_MAX_LENGTH)
|
18
|
+
remove_long_items(obj.compact[0..ARRAY_MAX_LENGTH-2] << ["TRUNCATED", "at #{ ARRAY_MAX_LENGTH } (#{obj.length})"])
|
19
|
+
when (String === obj and obj.length > STRING_MAX_LENGTH)
|
20
|
+
obj[0..STRING_MAX_LENGTH-1] << " TRUNCATED at #{STRING_MAX_LENGTH} (#{obj.length})"
|
21
|
+
when Hash === obj
|
22
|
+
new = {}
|
23
|
+
obj.each do |k,v|
|
24
|
+
new[k] = remove_long_items(v)
|
25
|
+
end
|
26
|
+
new
|
27
|
+
when Array === obj
|
28
|
+
obj.collect do |e| remove_long_items(e) end
|
29
|
+
else
|
30
|
+
obj
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
10
34
|
def self.ensembl_server(organism)
|
11
35
|
date = organism.split("/")[1]
|
12
36
|
if date.nil?
|
@@ -192,6 +216,77 @@ end
|
|
192
216
|
"val" => "V"
|
193
217
|
}
|
194
218
|
|
219
|
+
def self.fast_align(reference, sequence)
|
220
|
+
init_gap = -1
|
221
|
+
gap = -2
|
222
|
+
diff = -2
|
223
|
+
same = 2
|
224
|
+
|
225
|
+
cols = sequence.length + 1
|
226
|
+
rows = reference.length + 1
|
227
|
+
|
228
|
+
a = NArray.int(cols, rows)
|
229
|
+
|
230
|
+
|
231
|
+
for spos in 0..cols-1 do a[spos, 0] = spos * init_gap end
|
232
|
+
for rpos in 0..rows-1 do a[0, rpos] = rpos * init_gap end
|
233
|
+
|
234
|
+
for spos in 1..cols-1 do
|
235
|
+
for rpos in 1..rows-1 do
|
236
|
+
match = a[spos-1,rpos-1] + (sequence[spos-1] != reference[rpos-1] ? diff : same)
|
237
|
+
skip_sequence = a[spos-1,rpos] + gap
|
238
|
+
skip_reference = a[spos,rpos-1] + gap
|
239
|
+
a[spos,rpos] = [match, skip_sequence, skip_reference].max
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
start = Misc.max(a[-1,0..rows-1])
|
244
|
+
start_pos = a[-1,0..rows-1].to_a.index start
|
245
|
+
|
246
|
+
ref = ''
|
247
|
+
seq = ''
|
248
|
+
rpos = start_pos
|
249
|
+
spos = cols - 1
|
250
|
+
|
251
|
+
while spos > 0 and rpos > 0
|
252
|
+
score = a[spos,rpos]
|
253
|
+
score_match = a[spos-1,rpos-1]
|
254
|
+
score_skip_reference = a[spos,rpos-1]
|
255
|
+
score_skip_sequence = a[spos-1,rpos]
|
256
|
+
|
257
|
+
case
|
258
|
+
when score == score_match + (sequence[spos-1] != reference[rpos-1] ? diff : same)
|
259
|
+
ref << reference[rpos-1]
|
260
|
+
seq << sequence[spos-1]
|
261
|
+
spos -= 1
|
262
|
+
rpos -= 1
|
263
|
+
when score == score_skip_reference + gap
|
264
|
+
ref << reference[rpos-1]
|
265
|
+
seq << '-'
|
266
|
+
rpos -= 1
|
267
|
+
when score == score_skip_sequence + gap
|
268
|
+
seq << sequence[spos-1]
|
269
|
+
ref << '-'
|
270
|
+
spos -= 1
|
271
|
+
else
|
272
|
+
raise "stop"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
while (rpos > 0)
|
277
|
+
ref << reference[rpos-1]
|
278
|
+
seq = seq << '-'
|
279
|
+
rpos -= 1
|
280
|
+
end
|
281
|
+
|
282
|
+
while (spos > 0)
|
283
|
+
seq << sequence[spos-1]
|
284
|
+
ref = ref + '-'
|
285
|
+
spos -= 1
|
286
|
+
end
|
287
|
+
|
288
|
+
[ref.reverse + reference[start_pos..-1], seq.reverse + '-' * (rows - start_pos - 1)]
|
289
|
+
end
|
195
290
|
def self.IUPAC_to_base(iupac)
|
196
291
|
IUPAC2BASE[iupac]
|
197
292
|
end
|
@@ -366,10 +461,14 @@ end
|
|
366
461
|
|
367
462
|
def self.lock(file, *args)
|
368
463
|
FileUtils.mkdir_p File.dirname(File.expand_path(file)) unless File.exists? File.dirname(File.expand_path(file))
|
369
|
-
|
370
|
-
|
371
|
-
|
464
|
+
|
465
|
+
res = nil
|
466
|
+
|
467
|
+
Lockfile.new(file + '.lock') do
|
468
|
+
res = yield file, *args
|
372
469
|
end
|
470
|
+
|
471
|
+
res
|
373
472
|
end
|
374
473
|
|
375
474
|
def self.common_path(dir, file)
|
@@ -410,21 +509,23 @@ end
|
|
410
509
|
end
|
411
510
|
|
412
511
|
def self.sensiblewrite(path, content)
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
512
|
+
Misc.lock path do
|
513
|
+
begin
|
514
|
+
case
|
515
|
+
when String === content
|
516
|
+
File.open(path, 'w') do |f| f.write content end
|
517
|
+
when (IO === content or StringIO === content)
|
518
|
+
File.open(path, 'w') do |f| while l = content.gets; f.write l; end end
|
519
|
+
else
|
520
|
+
File.open(path, 'w') do |f| end
|
521
|
+
end
|
522
|
+
rescue Interrupt
|
523
|
+
FileUtils.rm_f path
|
524
|
+
raise "Interrupted (Ctrl-c)"
|
525
|
+
rescue Exception
|
526
|
+
FileUtils.rm_f path
|
527
|
+
raise $!
|
421
528
|
end
|
422
|
-
rescue Interrupt
|
423
|
-
FileUtils.rm_f path
|
424
|
-
raise "Interrupted (Ctrl-c)"
|
425
|
-
rescue Exception
|
426
|
-
FileUtils.rm_f path
|
427
|
-
raise $!
|
428
529
|
end
|
429
530
|
end
|
430
531
|
|
@@ -456,12 +557,18 @@ end
|
|
456
557
|
next if k == :monitor or k == "monitor" or k == :in_situ_persistence or k == "in_situ_persistence"
|
457
558
|
v = hash[k]
|
458
559
|
case
|
560
|
+
when TrueClass === v
|
561
|
+
str << k.to_s << "=>true"
|
562
|
+
when FalseClass === v
|
563
|
+
str << k.to_s << "=>false"
|
459
564
|
when Hash === v
|
460
565
|
str << k.to_s << "=>" << hash2md5(v)
|
461
566
|
when Symbol === v
|
462
567
|
str << k.to_s << "=>" << v.to_s
|
463
568
|
when String === v
|
464
|
-
str << k.to_s << "=>" << v
|
569
|
+
str << k.to_s << "=>" << v[0..10000]
|
570
|
+
when Array === v
|
571
|
+
str << k.to_s << "=>[" << v[0..1000] * "," << "]"
|
465
572
|
else
|
466
573
|
v_ins = v.inspect
|
467
574
|
|
@@ -469,7 +576,7 @@ end
|
|
469
576
|
when v_ins =~ /:0x0/
|
470
577
|
str << k.to_s << "=>" << v_ins.sub(/:0x[a-f0-9]+@/,'')
|
471
578
|
else
|
472
|
-
str << k.to_s << "=>" <<
|
579
|
+
str << k.to_s << "=>" << v_ins
|
473
580
|
end
|
474
581
|
|
475
582
|
end
|
data/lib/rbbt/util/open.rb
CHANGED
@@ -104,9 +104,7 @@ module Open
|
|
104
104
|
|
105
105
|
def self.add_cache(url, data, options = {})
|
106
106
|
file = File.join(REMOTE_CACHEDIR, digest_url(url, options))
|
107
|
-
Misc.
|
108
|
-
Misc.sensiblewrite(file, data)
|
109
|
-
end
|
107
|
+
Misc.sensiblewrite(file, data)
|
110
108
|
end
|
111
109
|
|
112
110
|
# Grep
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -19,7 +19,14 @@ class Step
|
|
19
19
|
|
20
20
|
def info
|
21
21
|
return {} if not File.exists? info_file
|
22
|
-
|
22
|
+
begin
|
23
|
+
File.open(info_file) do |file|
|
24
|
+
YAML.load(file) || {}
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
Log.debug "Error loading yaml: " + Open.read(info_file)
|
28
|
+
raise $!
|
29
|
+
end
|
23
30
|
end
|
24
31
|
|
25
32
|
def set_info(key, value)
|
@@ -44,19 +51,23 @@ class Step
|
|
44
51
|
end
|
45
52
|
|
46
53
|
def message(message)
|
47
|
-
set_info(:messages, messages << message)
|
54
|
+
set_info(:messages, (messages || []) << message)
|
48
55
|
end
|
49
56
|
|
50
57
|
def log(status, message = nil)
|
51
58
|
if message
|
52
|
-
Log.low "#{ status }
|
59
|
+
Log.low "[#{ status }] #{ message }: #{path}"
|
53
60
|
else
|
54
|
-
Log.low "#{ status }"
|
61
|
+
Log.low "[#{ status }]: #{path}"
|
55
62
|
end
|
56
63
|
self.status = status
|
57
64
|
message(message) unless message.nil?
|
58
65
|
end
|
59
66
|
|
67
|
+
def started?
|
68
|
+
File.exists? info_file
|
69
|
+
end
|
70
|
+
|
60
71
|
def done?
|
61
72
|
status = info[:status]
|
62
73
|
status == :done or status == :error
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -4,14 +4,15 @@ require 'rbbt/util/log'
|
|
4
4
|
require 'rbbt/workflow/accessor'
|
5
5
|
|
6
6
|
class Step
|
7
|
-
attr_accessor :path, :task, :inputs, :dependencies
|
7
|
+
attr_accessor :path, :task, :inputs, :dependencies, :bindings
|
8
8
|
attr_accessor :pid
|
9
9
|
|
10
10
|
class Aborted < Exception; end
|
11
11
|
|
12
|
-
def initialize(path, task = nil, inputs = nil, dependencies = nil)
|
12
|
+
def initialize(path, task = nil, inputs = nil, dependencies = nil, bindings = nil)
|
13
13
|
@path = path
|
14
14
|
@task = task
|
15
|
+
@bindings = bindings
|
15
16
|
@dependencies = case
|
16
17
|
when dependencies.nil?
|
17
18
|
[]
|
@@ -30,14 +31,13 @@ class Step
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def exec
|
33
|
-
result = @task.exec_in self, *@inputs
|
34
|
+
result = @task.exec_in((bindings ? bindings : self), *@inputs)
|
34
35
|
prepare_result result, @task.result_description
|
35
36
|
end
|
36
37
|
|
37
38
|
def join
|
38
39
|
if @pid.nil?
|
39
40
|
while not done? do
|
40
|
-
Log.debug "Waiting: #{info[:step]}"
|
41
41
|
sleep 5
|
42
42
|
end
|
43
43
|
else
|
@@ -50,12 +50,22 @@ class Step
|
|
50
50
|
|
51
51
|
def run(no_load = false)
|
52
52
|
result = Persist.persist "Job", @task.result_type, :file => @path, :check => rec_dependencies.collect{|dependency| dependency.path}.uniq, :no_load => no_load do
|
53
|
-
|
53
|
+
FileUtils.rm info_file if File.exists? info_file
|
54
|
+
log((task.name || "unnamed task"), "Starting task")
|
54
55
|
set_info :dependencies, @dependencies.collect{|dep| [dep.task.name, dep.name]}
|
55
|
-
@dependencies.each{|dependency|
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
@dependencies.each{|dependency|
|
57
|
+
log dependency.task.name || "dependency", "Processing dependency: #{ dependency.path }"
|
58
|
+
dependency.run true
|
59
|
+
}
|
60
|
+
set_info :status, :started
|
61
|
+
set_info :inputs, Misc.remove_long_items(Misc.zip2hash(task.inputs, @inputs)) unless task.inputs.nil?
|
62
|
+
res = begin
|
63
|
+
exec
|
64
|
+
rescue Exception
|
65
|
+
set_info :backtrace, $!.backtrace
|
66
|
+
log(:error, "#{$!.class}: #{$!.message}")
|
67
|
+
raise $!
|
68
|
+
end
|
59
69
|
set_info :status, :done
|
60
70
|
res
|
61
71
|
end
|
@@ -66,11 +76,12 @@ class Step
|
|
66
76
|
def fork
|
67
77
|
raise "Can not fork: Step is waiting for proces #{@pid} to finish" if not @pid.nil?
|
68
78
|
@pid = Process.fork do
|
79
|
+
trap(:INT) { raise Step::Aborted.new "INT signal recieved" }
|
80
|
+
FileUtils.mkdir_p File.dirname(path) unless File.exists? File.dirname(path)
|
69
81
|
begin
|
70
|
-
trap(:INT) { raise Step::Aborted.new "INT signal recieved" }
|
71
82
|
run
|
72
|
-
rescue
|
73
|
-
|
83
|
+
rescue
|
84
|
+
exit -1
|
74
85
|
end
|
75
86
|
end
|
76
87
|
set_info :pid, @pid
|
@@ -5,6 +5,18 @@ require 'test/unit'
|
|
5
5
|
|
6
6
|
class TestTSV < Test::Unit::TestCase
|
7
7
|
|
8
|
+
def test_find
|
9
|
+
name = 'test_name_for_unexistent_file'
|
10
|
+
path = Path.setup "tmp/#{ name }"
|
11
|
+
|
12
|
+
TmpFile.with_file do |dir|
|
13
|
+
assert File.join(ENV['HOME'], path), path.find(nil, nil, {:root => File.join(dir, '{TOPLEVEL}/{SUBPATH}'), :default => :user, :user => File.join(ENV['HOME'], "{TOPLEVEL}", "{SUBPATH}")})
|
14
|
+
FileUtils.mkdir_p File.dirname(File.join(dir, path))
|
15
|
+
FileUtils.touch File.join(dir, path)
|
16
|
+
assert File.join(dir, "tmp/test"), path.find(nil, nil, {:root => File.join(dir, '{TOPLEVEL}/{SUBPATH}'), :default => :user, :user => File.join(ENV['HOME'], "{TOPLEVEL}", "{SUBPATH}")})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
8
20
|
def test_prev
|
9
21
|
path = Path.setup "/tmp"
|
10
22
|
assert_equal "/tmp/bar/foo", path.foo("bar")
|
data/test/rbbt/test_persist.rb
CHANGED
@@ -8,6 +8,7 @@ module TestAnnotation
|
|
8
8
|
|
9
9
|
self.annotation :test_annotation
|
10
10
|
end
|
11
|
+
|
11
12
|
class TestPersist < Test::Unit::TestCase
|
12
13
|
|
13
14
|
def test_annotation_persist
|
@@ -40,6 +41,51 @@ class TestPersist < Test::Unit::TestCase
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
44
|
+
def test_bdb
|
45
|
+
TmpFile.with_file do |tmp|
|
46
|
+
repo = Persist.open_tokyocabinet(tmp, true, :double, TokyoCabinet::BDB)
|
47
|
+
repo["test:string1"] = [["STR1"]]
|
48
|
+
repo["test:string2"] = [["STR2"]]
|
49
|
+
repo["other_test:string3"] = [["STR2"]]
|
50
|
+
|
51
|
+
assert_equal ["test:string1", "test:string2"].sort, repo.range("test:" << 0.chr, false, "test:" << 255.chr, false).sort
|
52
|
+
assert_equal ["other_test:string3"].sort, repo.range("other_test:" << 0.chr, false, "other_test:" << 255.chr, false).sort
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_annotation_persist_repo
|
57
|
+
TmpFile.with_file do |tmp|
|
58
|
+
repo = Persist.open_tokyocabinet(tmp, true, :list, TokyoCabinet::BDB)
|
59
|
+
|
60
|
+
entity1 = "Entity 1"
|
61
|
+
entity2 = "Entity 2"
|
62
|
+
|
63
|
+
TestAnnotation.setup(entity1, :test_annotation => "1")
|
64
|
+
TestAnnotation.setup(entity2, :test_annotation => "2")
|
65
|
+
|
66
|
+
annotations = [entity1, entity2]
|
67
|
+
|
68
|
+
persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
|
69
|
+
annotations
|
70
|
+
end
|
71
|
+
|
72
|
+
assert_equal "Entity 1", persisted_annotations.first
|
73
|
+
assert_equal "Entity 2", persisted_annotations.last
|
74
|
+
assert_equal "1", persisted_annotations.first.test_annotation
|
75
|
+
assert_equal "2", persisted_annotations.last.test_annotation
|
76
|
+
|
77
|
+
persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
|
78
|
+
annotations
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal "Entity 1", persisted_annotations.sort.first
|
82
|
+
assert_equal "Entity 2", persisted_annotations.sort.last
|
83
|
+
assert_equal "1", persisted_annotations.sort.first.test_annotation
|
84
|
+
assert_equal "2", persisted_annotations.sort.last.test_annotation
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
43
89
|
def test_array_persist
|
44
90
|
TmpFile.with_file do |tmp|
|
45
91
|
10.times do
|
data/test/rbbt/tsv/test_index.rb
CHANGED
data/test/rbbt/util/test_misc.rb
CHANGED
@@ -96,7 +96,6 @@ class TestMisc < Test::Unit::TestCase
|
|
96
96
|
a = [[1],[2]]
|
97
97
|
a = NamedArray.setup a, %w(1 2)
|
98
98
|
a.merge [3,4]
|
99
|
-
ddd a
|
100
99
|
assert_equal [1,3], a[0]
|
101
100
|
end
|
102
101
|
|
@@ -151,6 +150,18 @@ class TestMisc < Test::Unit::TestCase
|
|
151
150
|
assert_equal Math.sqrt(2), Misc.sd([1,3])
|
152
151
|
end
|
153
152
|
|
153
|
+
def test_align_small
|
154
|
+
reference = "AABCDEBD"
|
155
|
+
sequence = "ABCD"
|
156
|
+
assert_equal '-ABCD---', Misc.fast_align(reference, sequence).last
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_align_real
|
160
|
+
reference = "SGNECNKAIDGNKDTFWHTFYGANGDPKPPPHTYTIDMKTTQNVNGLSMLPRQDGNQNGWIGRHEVYLSSDGTNW"
|
161
|
+
sequence = "TYTIDMKTTQNVNGLSML"
|
162
|
+
assert_equal "--------------------------------TYTIDMKTTQNVNGLSML-------------------------", Misc.fast_align(reference, sequence).last
|
163
|
+
end
|
164
|
+
|
154
165
|
# def test_divide
|
155
166
|
# assert_equal 2, Misc.divide(%w(1 2 3 4 5 6 7 8 9),2).length
|
156
167
|
# end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 4
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 4.
|
10
|
+
version: 4.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Miguel Vazquez
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
19
|
-
default_executable:
|
18
|
+
date: 2012-01-31 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rake
|
@@ -116,6 +115,20 @@ dependencies:
|
|
116
115
|
version: "0"
|
117
116
|
type: :runtime
|
118
117
|
version_requirements: *id007
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: narray
|
120
|
+
prerelease: false
|
121
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
version: "0"
|
130
|
+
type: :runtime
|
131
|
+
version_requirements: *id008
|
119
132
|
description: Utilities for handling tsv files, caches, etc
|
120
133
|
email: miguel.vazquez@cnio.es
|
121
134
|
executables:
|
@@ -209,7 +222,6 @@ files:
|
|
209
222
|
- bin/rbbt_query.rb
|
210
223
|
- bin/rbbt_exec.rb
|
211
224
|
- bin/rbbt_Rutil.rb
|
212
|
-
has_rdoc: true
|
213
225
|
homepage: http://github.com/mikisvaz/rbbt-util
|
214
226
|
licenses: []
|
215
227
|
|
@@ -239,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
239
251
|
requirements: []
|
240
252
|
|
241
253
|
rubyforge_project:
|
242
|
-
rubygems_version: 1.
|
254
|
+
rubygems_version: 1.8.12
|
243
255
|
signing_key:
|
244
256
|
specification_version: 3
|
245
257
|
summary: Utilities for the Ruby Bioinformatics Toolkit (rbbt)
|