rbbt-util 5.0.1 → 5.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.
@@ -0,0 +1,174 @@
1
+ module AnnotatedArray
2
+ def double_array
3
+ AnnotatedArray === self.send(:[], 0, true)
4
+ end
5
+
6
+ def first
7
+ self[0]
8
+ end
9
+
10
+ def last
11
+ self[-1]
12
+ end
13
+
14
+ def [](pos, clean = false)
15
+
16
+ value = super(pos)
17
+ return value if value.nil? or clean
18
+
19
+ value = value.dup if value.frozen?
20
+
21
+ value = annotate(value)
22
+
23
+ value.extend AnnotatedArray if Array === value
24
+
25
+ value.container = self
26
+ value.container_index = pos
27
+
28
+ value
29
+ end
30
+
31
+ def each(&block)
32
+
33
+ pos = 0
34
+ super do |value|
35
+
36
+ if value.nil?
37
+
38
+ block.call value
39
+ else
40
+
41
+ value = value.dup if value.frozen?
42
+
43
+ value = annotate(value)
44
+
45
+ value.extend AnnotatedArray if Array === value
46
+
47
+ value.container = self
48
+ value.container_index = pos
49
+
50
+ pos += 1
51
+
52
+ block.call value
53
+ end
54
+ end
55
+ end
56
+
57
+ def collect(&block)
58
+
59
+ if block_given?
60
+
61
+ res = []
62
+ each do |value|
63
+ res << yield(value)
64
+ end
65
+
66
+ res
67
+ else
68
+
69
+ res = []
70
+ each do |value|
71
+ res << value
72
+ end
73
+
74
+ res
75
+ end
76
+ end
77
+
78
+ def select(method = nil, *args)
79
+
80
+ if method
81
+
82
+ res = self.zip( self.send(method, *args) ).
83
+ select{|e,result| result }.
84
+ collect{|element,r| element }
85
+ else
86
+
87
+ return self unless block_given?
88
+
89
+ res = []
90
+ each do |value|
91
+ res << value if yield(value)
92
+ end
93
+ end
94
+
95
+ annotate(res)
96
+ res.extend AnnotatedArray
97
+
98
+ res
99
+ end
100
+
101
+ def reject
102
+ res = []
103
+
104
+ each do |value|
105
+ res << value unless yield(value)
106
+ end
107
+
108
+ annotate(res)
109
+ res.extend AnnotatedArray
110
+
111
+ res
112
+ end
113
+
114
+ def select
115
+ res = []
116
+
117
+ each do |value|
118
+ res << value if yield(value)
119
+ end
120
+
121
+ annotate(res)
122
+ res.extend AnnotatedArray
123
+
124
+ res
125
+ end
126
+
127
+ def subset(list)
128
+
129
+ res = (self & list)
130
+
131
+ annotate(res)
132
+ res.extend AnnotatedArray
133
+
134
+ res
135
+ end
136
+
137
+ def remove(list)
138
+
139
+ res = (self - list)
140
+
141
+ annotate(res)
142
+ res.extend AnnotatedArray
143
+
144
+ res
145
+ end
146
+
147
+ def sort(&block)
148
+ res = self.collect.sort(&block).collect{|value| value.respond_to?(:clean_annotations) ? value.clean_annotations.dup : value.dup }
149
+
150
+ annotate(res)
151
+ res.extend AnnotatedArray
152
+
153
+ res
154
+ end
155
+
156
+
157
+ %w(compact uniq flatten reverse sort_by).each do |method|
158
+
159
+ self.module_eval <<-EOC
160
+
161
+ def #{method}
162
+ res = super
163
+
164
+ annotate(res)
165
+ res.extend AnnotatedArray
166
+
167
+ res
168
+ end
169
+
170
+ EOC
171
+ end
172
+ end
173
+
174
+
@@ -0,0 +1,206 @@
1
+ require 'json'
2
+
3
+ module Annotated
4
+
5
+ def self.load(object, info)
6
+ annotation_types = info.delete(:annotation_types) || info.delete("annotation_types") || []
7
+ annotation_types = annotation_types.split("|") if String === annotation_types
8
+
9
+ return object if annotation_types.nil? or annotation_types.empty?
10
+
11
+ annotated_array = false
12
+ annotated_array = true if (info.delete(:annotated_array) || info.delete("annotated_array")).to_s == "true"
13
+ entity_id = info.delete(:entity_id) || info.delete("entity_id")
14
+
15
+ annotation_types.each do |mod|
16
+ mod = Misc.string2const(mod) if String === mod
17
+ object.extend mod
18
+ end
19
+
20
+ object.instance_variable_set(:@annotation_values, info)
21
+
22
+ object.instance_variable_set(:@id, entity_id) if entity_id
23
+
24
+ object.extend AnnotatedArray if annotated_array
25
+
26
+ object
27
+ end
28
+
29
+ def self.resolve_array(entry)
30
+ if entry =~ /^Array:/
31
+ entry["Array:".length..-1].split("|")
32
+ else
33
+ entry
34
+ end
35
+ end
36
+
37
+ def self.load_tsv_values(id, values, *fields)
38
+ fields = fields.flatten
39
+ info = {}
40
+ literal_pos = fields.index "literal"
41
+
42
+ object = case
43
+ when literal_pos
44
+ values[literal_pos]
45
+ else
46
+ id.dup
47
+ end
48
+
49
+ object = resolve_array(object)
50
+
51
+ if Array === values.first
52
+ Misc.zip_fields(values).collect do |list|
53
+ fields.each_with_index do |field,i|
54
+ next if field == "literal"
55
+ if field == "JSON"
56
+ JSON.parse(list[i]).each do |key, value|
57
+ info[key.to_sym] = value
58
+ end
59
+ else
60
+ info[field.to_sym] = resolve_array(list[i])
61
+ end
62
+ end
63
+ end
64
+ else
65
+ fields.each_with_index do |field,i|
66
+ next if field == "literal"
67
+ if field == "JSON"
68
+ JSON.parse(values[i]).each do |key, value|
69
+ info[key.to_sym] = value
70
+ end
71
+ else
72
+ info[field.to_sym] = resolve_array(values[i])
73
+ end
74
+ end
75
+ end
76
+
77
+ self.load(object, info)
78
+
79
+ object
80
+ end
81
+
82
+ def self.load_tsv(tsv)
83
+ tsv.with_unnamed do
84
+ annotated_entities = tsv.collect do |id, values|
85
+ Annotated.load_tsv_values(id, values, tsv.fields)
86
+ end
87
+
88
+ case tsv.key_field
89
+ when "List"
90
+ annotated_entities.first
91
+ else
92
+ annotated_entities
93
+ end
94
+ end
95
+ end
96
+
97
+
98
+ def self.tsv(annotations, *fields)
99
+ return nil if annotations.nil?
100
+
101
+ fields = case
102
+
103
+ when ((fields.compact.empty?) and not annotations.empty?)
104
+ fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
105
+ fields << :annotation_types
106
+
107
+ when (fields == [:literal] and not annotations.empty?)
108
+ fields << :literal
109
+
110
+ when (fields == [:all] and Annotated === annotations)
111
+ fields = [:annotation_types] + annotations.annotations
112
+ fields << :annotated_array if AnnotatedArray === annotations
113
+ fields << :literal
114
+
115
+ when (fields == [:all] and not annotations.empty?)
116
+ raise "Input array must be annotated or its elements must be" if not Annotated === annotations.compact.first and not Array === annotations.compact.first
117
+ raise "Input array must be annotated or its elements must be. No duble arrays of singly annotated entities." if not Annotated === annotations.compact.first and Array === annotations.compact.first
118
+ fields = [:annotation_types] + (Annotated === annotations ?
119
+ annotations.annotations:
120
+ annotations.compact.first.annotations)
121
+ fields << :literal
122
+
123
+ when annotations.empty?
124
+ [:annotation_types, :literal]
125
+
126
+ else
127
+ fields.flatten
128
+
129
+ end
130
+
131
+ fields = fields.collect{|f| f.to_s}
132
+
133
+ case
134
+
135
+ when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
136
+ tsv = TSV.setup({}, :key_field => "List", :fields => fields, :type => :list, :unnamed => true)
137
+
138
+ annot_id = annotations.id
139
+ tsv[annot_id] = annotations.tsv_values(*fields).dup
140
+
141
+ when Array === annotations
142
+ tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
143
+
144
+ annotations.compact.each_with_index do |annotation,i|
145
+ tsv[annotation.id + ":" << i.to_s] = annotation.tsv_values(*fields).dup
146
+ end
147
+
148
+ else
149
+ raise "Annotations need to be an Array to create TSV"
150
+
151
+ end
152
+
153
+ tsv
154
+ end
155
+
156
+ def tsv_values(*fields)
157
+ if Array === self and (not AnnotatedArray === self or self.double_array)
158
+ Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
159
+ else
160
+ fields = fields.flatten
161
+
162
+ info = self.info
163
+
164
+ values = []
165
+
166
+ fields.each do |field|
167
+ values << case
168
+
169
+ when Proc === field
170
+ field.call(self)
171
+
172
+ when field == "JSON"
173
+ if AnnotatedArray === self
174
+ info.merge(:annotated_array => true).to_json
175
+ else
176
+ info.to_json
177
+ end
178
+
179
+ when field == "annotation_types"
180
+ annotation_types.collect{|t| t.to_s} * "|"
181
+
182
+ when field == "annotated_array"
183
+ AnnotatedArray === self
184
+
185
+ when field == "literal"
186
+ (Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
187
+
188
+ when info.include?(field.to_sym)
189
+ res = info[field.to_sym]
190
+ Array === res ? "Array:" << res * "|" : res
191
+
192
+ when self.respond_to?(field)
193
+ res = self.send(field)
194
+ Array === res ? "Array:"<< res * "|" : res
195
+
196
+ end
197
+ end
198
+
199
+
200
+ values
201
+ end
202
+ end
203
+
204
+
205
+ end
206
+
@@ -9,11 +9,37 @@ module TSV
9
9
  attr_accessor :unnamed, :serializer_module, :entity_options
10
10
 
11
11
  def entity_options
12
- options = namespace ? {:namespace => namespace, :organism => namespace} : {}
13
- if @entity_options
14
- options.merge(@entity_options)
12
+ if @entity_options.nil?
13
+ @entity_options = namespace ? {:namespace => namespace, :organism => namespace} : {}
14
+ @entity_templates = nil
15
+ end
16
+ @entity_options
17
+ end
18
+
19
+ def prepare_entity(entity, field, options = {})
20
+ return entity if entity.nil?
21
+ return entity unless defined? Entity
22
+ entity = entity if options.delete :dup_array
23
+ @entity_templates ||= {}
24
+ if (template = @entity_templates[field])
25
+ entity = template.annotate(entity.frozen? ? entity.dup : entity)
26
+ entity.extend AnnotatedArray if Array === entity
27
+ entity
15
28
  else
16
- options
29
+ if @entity_templates.include? field
30
+ entity
31
+ else
32
+ template = Misc.prepare_entity("TEMPLATE", field, options)
33
+ if Annotated === template
34
+ @entity_templates[field] = template
35
+ entity = template.annotate(entity.frozen? ? entity.dup : entity)
36
+ entity.extend AnnotatedArray if Array === entity
37
+ entity
38
+ else
39
+ @entity_templates[field] = nil
40
+ entity
41
+ end
42
+ end
17
43
  end
18
44
  end
19
45
 
@@ -87,7 +113,7 @@ module TSV
87
113
  when :flat, :single
88
114
  value = value.dup if value.frozen?
89
115
 
90
- value = Misc.prepare_entity(value, fields.first, entity_options)
116
+ value = prepare_entity(value, fields.first, entity_options)
91
117
  end
92
118
  value
93
119
  end
@@ -100,7 +126,7 @@ module TSV
100
126
  keys = tsv_clean_keys - ENTRY_KEYS
101
127
  return keys if @unnamed or key_field.nil?
102
128
 
103
- Misc.prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
129
+ prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
104
130
  end
105
131
 
106
132
  def tsv_values
@@ -111,7 +137,7 @@ module TSV
111
137
  when :double, :list
112
138
  values.each{|value| NamedArray.setup value, fields, nil, entity_options}
113
139
  when :flat, :single
114
- values = values.collect{|v| Misc.prepare_entity(v, fields.first, entity_options)}
140
+ values = values.collect{|v| prepare_entity(v, fields.first, entity_options)}
115
141
  end
116
142
 
117
143
  values
@@ -135,10 +161,10 @@ module TSV
135
161
  when :double, :list
136
162
  NamedArray.setup value, fields, key, entity_options if Array === value
137
163
  when :flat, :single
138
- Misc.prepare_entity(value, fields.first, entity_options)
164
+ prepare_entity(value, fields.first, entity_options)
139
165
  end
140
166
  end
141
- key = Misc.prepare_entity(key, key_field, entity_options)
167
+ key = prepare_entity(key, key_field, entity_options)
142
168
  end
143
169
 
144
170
  yield key, value if block_given?
@@ -162,10 +188,10 @@ module TSV
162
188
  when :double, :list
163
189
  NamedArray.setup value, fields, key, entity_options if Array === value
164
190
  when :flat, :single
165
- value = Misc.prepare_entity(value, fields.first, entity_options)
191
+ value = prepare_entity(value, fields.first, entity_options)
166
192
  end
167
193
  end
168
- key = Misc.prepare_entity(key, key_field, entity_options)
194
+ key = prepare_entity(key, key_field, entity_options)
169
195
  end
170
196
 
171
197
 
@@ -229,14 +255,14 @@ module TSV
229
255
  if fields == :all
230
256
  if just_keys
231
257
  keys = elems.sort_by{|key, value| key }.collect{|key, values| key}
232
- keys = Misc.prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
258
+ keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
233
259
  else
234
260
  elems.sort_by{|key, value| key }
235
261
  end
236
262
  else
237
263
  if just_keys
238
264
  keys = elems.sort_by{|key, value| value }.collect{|key, value| key}
239
- keys = Misc.prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
265
+ keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
240
266
  keys
241
267
  else
242
268
  elems.sort_by{|key, value| value }.collect{|key, value| [key, self[key]]}
@@ -345,8 +371,8 @@ end
345
371
  end
346
372
 
347
373
  entry :key_field,
348
- :fields,
349
374
  :type,
375
+ :fields,
350
376
  :cast,
351
377
  :identifiers,
352
378
  :namespace,
@@ -358,10 +384,22 @@ end
358
384
  if @fields.nil? or @unnamed
359
385
  @fields
360
386
  else
361
- NamedArray.setup @fields, @fields, nil, entity_options
387
+ @named_fields ||= NamedArray.setup @fields, @fields, nil, entity_options
362
388
  end
363
389
  end
364
390
 
391
+ def namespace=(value)
392
+ self.tsv_clean_set_brackets "__tsv_hash_namespace", value.nil? ? NIL_YAML : value.to_yaml
393
+ @namespace = value
394
+ @entity_options = nil
395
+ end
396
+
397
+ def fields=(value)
398
+ self.tsv_clean_set_brackets "__tsv_hash_fields", value.nil? ? NIL_YAML : value.to_yaml
399
+ @fields = value
400
+ @named_fields = nil
401
+ end
402
+
365
403
  def self.zip_fields(list, fields = nil)
366
404
  return [] if list.nil? || list.empty?
367
405
  fields ||= list.fields if list.respond_to? :fields