rbbt-util 4.2.0 → 4.3.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/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)
|