rbbt-util 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -88,7 +88,7 @@ module Persist
88
88
  database
89
89
  end
90
90
 
91
- def self.persist_tsv(source, filename, options, persist_options = {})
91
+ def self.persist_tsv(source, filename, options = {}, persist_options = {})
92
92
  persist_options[:prefix] ||= "TSV"
93
93
 
94
94
  data = case
@@ -181,7 +181,7 @@ module Path
181
181
  if identifier_file_path.nil?
182
182
  []
183
183
  else
184
- [identifier_file_path.nil?]
184
+ [identifier_file_path]
185
185
  end
186
186
  end
187
187
  end
data/lib/rbbt/tsv.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
3
  require 'rbbt/util/misc'
4
+ require 'rbbt/util/named_array'
4
5
  require 'rbbt/util/log'
5
6
 
6
7
  require 'rbbt/persist'
@@ -38,10 +39,11 @@ module TSV
38
39
 
39
40
  filename = get_filename source
40
41
  serializer = Misc.process_options options, :serializer
42
+ unnamed = Misc.process_options options, :unnamed
41
43
 
42
44
  Log.debug "TSV open: #{ filename } - #{options.inspect}"
43
45
 
44
- Persist.persist_tsv source, filename, options, persist_options do |data|
46
+ data = Persist.persist_tsv source, filename, options, persist_options do |data|
45
47
  if serializer
46
48
  data.extend TSV unless TSV === data
47
49
  data.serializer = serializer
@@ -57,6 +59,10 @@ module TSV
57
59
 
58
60
  data
59
61
  end
62
+
63
+ data.unnamed = unnamed unless unnamed.nil?
64
+
65
+ data
60
66
  end
61
67
 
62
68
  def self.parse_header(stream, options = {})
@@ -68,13 +68,14 @@ module TSV
68
68
 
69
69
  def tsv_get_brackets(key)
70
70
  value = serialized_get(key)
71
- return value if @unnamed or fields.nil?
71
+ return value if value.nil? or @unnamed or fields.nil?
72
72
 
73
73
  case type
74
74
  when :double, :list
75
- NamedArray.setup value, fields, key
75
+ NamedArray.setup value, fields, key, namespace
76
76
  when :flat, :single
77
- Entity.formats[fields.first].setup(value, :format => fields.first) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
77
+ value = value.dup if value.frozen?
78
+ Entity.formats[fields.first].setup(value, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => fields.first})) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
78
79
  end
79
80
  value
80
81
  end
@@ -88,7 +89,7 @@ module TSV
88
89
  return keys if @unnamed or key_field.nil?
89
90
 
90
91
  if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? key_field
91
- Entity.formats[key_field].setup(keys.collect{|k| k.dup}, :format => key_field)
92
+ Entity.formats[key_field].setup(keys.collect{|k| k.dup}, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => key_field}) )
92
93
  else
93
94
  keys
94
95
  end
@@ -100,10 +101,10 @@ module TSV
100
101
 
101
102
  case type
102
103
  when :double, :list
103
- values.each{|value| NamedArray.setup value, fields }
104
+ values.each{|value| NamedArray.setup value, fields, nil, namespace }
104
105
  when :flat, :single
105
106
  values.each{|value|
106
- Entity.formats[fields.first].setup(value, :format => fields.first)
107
+ Entity.formats[fields.first].setup(value, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => fields.first}))
107
108
  } if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
108
109
  end
109
110
 
@@ -126,13 +127,13 @@ module TSV
126
127
  if not fields.nil?
127
128
  case type
128
129
  when :double, :list
129
- NamedArray.setup value, fields, key if Array === value
130
+ NamedArray.setup value, fields, key, namespace if Array === value
130
131
  when :flat, :single
131
- Entity.formats[fields.first].setup(value, :format => fields.first) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
132
+ Entity.formats[fields.first].setup(value, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => fields.first})) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
132
133
  end
133
134
  end
134
135
  if defined?(Entity) and not key_field.nil? and Entity.respond_to?(:formats) and Entity.formats.include? key_field
135
- key = Entity.formats[key_field].setup(key.dup, :format => key_field)
136
+ key = Entity.formats[key_field].setup(key.dup, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => key_field}))
136
137
  end
137
138
  end
138
139
 
@@ -155,13 +156,13 @@ module TSV
155
156
  if not fields.nil?
156
157
  case type
157
158
  when :double, :list
158
- NamedArray.setup value, fields, key if Array === value
159
+ NamedArray.setup value, fields, key, namespace if Array === value
159
160
  when :flat, :single
160
- Entity.formats[fields.first].setup(value, :format => fields.first) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
161
+ Entity.formats[fields.first].setup(value, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => fields.first})) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? fields.first
161
162
  end
162
163
  end
163
164
  if defined?(Entity) and not key_field.nil? and Entity.respond_to?(:formats) and Entity.formats.include? key_field
164
- key = Entity.formats[key_field].setup(key.dup, :format => key_field)
165
+ key = Entity.formats[key_field].setup(key.dup, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => key_field}))
165
166
  end
166
167
  end
167
168
 
@@ -215,13 +216,16 @@ module TSV
215
216
  if not block_given?
216
217
  if fields == :all
217
218
  if just_keys
218
- elems.sort_by{|key, value| key }.collect{|key, values| key}
219
+ keys = elems.sort_by{|key, value| key }.collect{|key, values| key}
220
+ Entity.formats[key_field].setup(keys, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => key_field})) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? key_field
219
221
  else
220
222
  elems.sort_by{|key, value| key }
221
223
  end
222
224
  else
223
225
  if just_keys
224
- elems.sort_by{|key, value| value }.collect{|key, value| key}
226
+ keys = elems.sort_by{|key, value| value }.collect{|key, value| key}
227
+ Entity.formats[key_field].setup(keys, (namespace ? {:namespace => namespace, :organism => namespace} : {}).merge({:format => fields.first})) if defined?(Entity) and Entity.respond_to?(:formats) and Entity.formats.include? key_field
228
+ keys
225
229
  else
226
230
  elems.sort_by{|key, value| value }.collect{|key, value| [key, self[key]]}
227
231
  end
@@ -299,8 +303,9 @@ if '#{entry}' == 'serializer'
299
303
 
300
304
  else
301
305
  class << self
302
-
306
+
303
307
  define_method :serialized_get do |key|
308
+ return nil unless self.include? key
304
309
  self.serializer_module.load(tsv_clean_get_brackets(key))
305
310
  end
306
311
 
@@ -335,7 +340,7 @@ end
335
340
  if @fields.nil? or @unnamed
336
341
  @fields
337
342
  else
338
- NamedArray.setup @fields, @fields
343
+ NamedArray.setup @fields, @fields, nil, namespace
339
344
  end
340
345
  end
341
346
 
@@ -235,19 +235,10 @@ module TSV
235
235
 
236
236
  if current_index.nil?
237
237
  current_index = next_file.index(:target => next_key, :fields => [current_key], :persist => persist_input)
238
+ current_index = current_index.select :key => data_file.keys
238
239
  else
239
240
  next_index = next_file.index :target => next_key, :fields => [current_key], :persist => persist_input
240
241
 
241
- if TokyoCabinet::HDB === current_index
242
- tmp = TSV.setup({}, :key_field => current_index.key_field, :fields => [current_index.fields], :serializer => current_index.serializer, :type => current_index.type, :filename => current_index.filename)
243
- current_index.with_unnamed do
244
- current_index.each do |key,value|
245
- tmp.tsv_clean_set_brackets(key, current_index.tsv_clean_get_brackets(key))
246
- end
247
- end
248
- current_index = tmp
249
- end
250
-
251
242
  next_index.with_unnamed do
252
243
  current_index.with_unnamed do
253
244
  current_index.process current_index.fields.first do |values|
@@ -245,6 +245,7 @@ module TSV
245
245
  data.key_field = new_key_field_name
246
246
  data.fields = new_field_names
247
247
  data.filename = filename
248
+ data.namespace = namespace
248
249
  data.type = type
249
250
  end
250
251
  end
@@ -281,9 +282,10 @@ module TSV
281
282
  new = TSV.setup({}, :key_field => key_field, :fields => fields, :type => type, :filename => filename, :identifiers => identifiers)
282
283
 
283
284
  new.key_field = key_field
284
- new.fields = fields.dup
285
+ new.fields = fields.dup unless fields.nil?
285
286
  new.type = type
286
287
  new.filename = filename
288
+ new.namespace = namespace
287
289
 
288
290
  case
289
291
  when (method.nil? and block_given?)
@@ -429,15 +431,31 @@ module TSV
429
431
  end
430
432
 
431
433
  def add_field(name = nil)
434
+ old_monitor = @monitor
435
+ @monitor = {:desc => "Adding field #{ name }"} if TrueClass === monitor
436
+
432
437
  through do |key, values|
433
438
  new_values = yield(key, values)
434
439
  new_values = [new_values] if type == :double and not Array === new_values
435
440
 
436
- values << new_values
441
+ case
442
+ when (values.nil? and (fields.nil? or fields.empty?))
443
+ values = [new_values]
444
+ when values.nil?
445
+ values = [nil] * fields.length + [new_values]
446
+ when NamedArray === values
447
+ values += [new_values]
448
+ else
449
+ values << new_values
450
+ end
437
451
  self[key] = values
438
452
  end
453
+ @monitor = old_monitor
439
454
 
440
- self.fields = self.fields + [name] if fields != nil and name != nil
455
+ if not fields.nil? and not name.nil?
456
+ fields = self.fields + [name]
457
+ self.fields = fields
458
+ end
441
459
 
442
460
  self
443
461
  end
@@ -1,7 +1,7 @@
1
1
  require 'rbbt/util/cmd'
2
2
  module TSV
3
3
  class Parser
4
- attr_accessor :header_hash, :sep, :sep2, :type, :key_position, :field_positions, :cast, :key_field, :fields, :fix, :select, :serializer, :straight, :take_all, :zipped
4
+ attr_accessor :header_hash, :sep, :sep2, :type, :key_position, :field_positions, :cast, :key_field, :fields, :fix, :select, :serializer, :straight, :take_all, :zipped, :namespace
5
5
 
6
6
  class SKIP_LINE < Exception; end
7
7
  class END_PARSING < Exception; end
@@ -62,6 +62,16 @@ module TSV
62
62
  line.split(@sep, -1)
63
63
  end
64
64
 
65
+ def get_values_single_from_flat(parts)
66
+ return parts.shift, parts.first if field_positions.nil? and key_position.nil?
67
+ if key_position == 0
68
+ [parts.shift, parts]
69
+ else
70
+ key = parts.shift
71
+ [parts, [key]]
72
+ end
73
+ end
74
+
65
75
  def get_values_single(parts)
66
76
  return parts.shift, parts.first if field_positions.nil? and key_position.nil?
67
77
  key = parts[key_position]
@@ -287,7 +297,8 @@ module TSV
287
297
  @header_hash = Misc.process_options(options, :header_hash) || "#"
288
298
  @sep = Misc.process_options(options, :sep) || "\t"
289
299
 
290
- options = parse_header(stream).merge options
300
+ header_options = parse_header(stream)
301
+ options = header_options.merge options
291
302
 
292
303
  @type = Misc.process_options(options, :type) || :double
293
304
  merge = Misc.process_options(options, :merge) || false
@@ -298,6 +309,7 @@ module TSV
298
309
  @fix = Misc.process_options(options, :fix)
299
310
  @select= Misc.process_options options, :select
300
311
  @zipped = Misc.process_options options, :zipped
312
+ @namespace = Misc.process_options options, :namespace
301
313
 
302
314
  case @type
303
315
  when :double
@@ -314,9 +326,15 @@ module TSV
314
326
  self.instance_eval do alias add_to_data add_to_data_no_merge_double end
315
327
  end
316
328
  when :single
317
- self.instance_eval do alias get_values get_values_single end
318
- self.instance_eval do alias cast_values cast_values_single end
319
- self.instance_eval do alias add_to_data add_to_data_no_merge_list end
329
+ if header_options[:type] == :flat
330
+ self.instance_eval do alias get_values get_values_single_from_flat end
331
+ self.instance_eval do alias cast_values cast_values_single end
332
+ self.instance_eval do alias add_to_data add_to_data_no_merge_double end
333
+ else
334
+ self.instance_eval do alias get_values get_values_single end
335
+ self.instance_eval do alias cast_values cast_values_single end
336
+ self.instance_eval do alias add_to_data add_to_data_no_merge_list end
337
+ end
320
338
  when :list
321
339
  self.instance_eval do alias get_values get_values_list end
322
340
  self.instance_eval do alias cast_values cast_values_list end
@@ -343,6 +361,7 @@ module TSV
343
361
  data.type = @type
344
362
  data.key_field = @key_field
345
363
  data.fields = @fields
364
+ data.namespace = @namespace
346
365
  data
347
366
  end
348
367
  end
data/lib/rbbt/tsv/util.rb CHANGED
@@ -46,7 +46,7 @@ module TSV
46
46
 
47
47
  path = Persist.persistence_path(filename, persist_options)
48
48
  TmpFile.with_file(values * "\n") do |value_file|
49
- cmd = "cat '#{ path }' | grep -w -F -f '#{ value_file }' |cut -f 2 |sort|uniq -c|sed 's/^ *//;s/ /\\t/'"
49
+ cmd = "cat '#{ path }' | grep -w -F -f '#{ value_file }' |cut -f 2 |sort|uniq -c|sed 's/^ *//;s/ /\t/'"
50
50
  begin
51
51
  TSV.open(CMD.cmd(cmd), :key_field => 1, :type => :single, :cast => :to_i)
52
52
  rescue
@@ -2,6 +2,7 @@ require 'rbbt/util/log'
2
2
  require 'set'
3
3
 
4
4
  module ChainMethods
5
+
5
6
  def self.chain_methods_extended(base)
6
7
  if not base.respond_to? :chain_prefix
7
8
  metaclass = class << base
@@ -14,10 +15,6 @@ module ChainMethods
14
15
  end
15
16
 
16
17
  metaclass.module_eval do
17
- def setup_chain(object)
18
- object.extend self
19
- end
20
-
21
18
  def setup_chains(base)
22
19
  raise "No prefix specified for #{self.to_s}" if self.chain_prefix.nil? or (String === self.chain_prefix and self.chain_prefix.empty?)
23
20
  methods = self.chained_methods
@@ -26,17 +23,6 @@ module ChainMethods
26
23
 
27
24
  prefix = self.chain_prefix
28
25
 
29
- #do_chain = true
30
- #methods.collect{|new_method|
31
- # original = new_method.sub(prefix.to_s + '_', '')
32
- # clean = prefix.to_s + '_clean_' + original
33
- # if base.respond_to? clean
34
- # do_chain = false
35
- # break
36
- # end
37
- #}
38
-
39
-
40
26
  if not base.respond_to?(:processed_chains) or base.processed_chains.nil? or not base.processed_chains.include? prefix
41
27
  class << base
42
28
  attr_accessor :processed_chains
@@ -61,6 +47,7 @@ module ChainMethods
61
47
  alias_method clean_method, original
62
48
  rescue
63
49
  end
50
+
64
51
  alias_method original, new_method
65
52
  end
66
53
  end
@@ -73,17 +60,19 @@ module ChainMethods
73
60
  alias prev_chain_methods_extended extended if methods.include? "extended"
74
61
 
75
62
  def extended(base)
76
- prev_chain_methods_extended(base) if methods.include? "prev_chain_methods_extended"
63
+ if self.respond_to? :prev_chain_methods_extended
64
+ prev_chain_methods_extended(base)
65
+ end
77
66
  setup_chains(base)
78
67
  end
79
68
  end
80
69
  end
81
- end
82
-
83
- base.chain_prefix = base.to_s.downcase.to_sym
84
- end
85
-
86
- def self.extended(base)
87
- chain_methods_extended(base)
88
70
  end
71
+
72
+ base.chain_prefix = base.to_s.downcase.to_sym
73
+ end
74
+
75
+ def self.extended(base)
76
+ chain_methods_extended(base)
77
+ end
89
78
  end
@@ -7,6 +7,65 @@ require 'net/smtp'
7
7
  module Misc
8
8
  class FieldNotFoundError < StandardError;end
9
9
 
10
+ def self.ensembl_server(organism)
11
+ date = organism.split("/")[1]
12
+ if date.nil?
13
+ "www.ensembl.org"
14
+ else
15
+ "#{ date }.archive.ensembl.org"
16
+ end
17
+ end
18
+
19
+ def self.filename?(string)
20
+ String === string and string.length > 0 and string.length < 250 and File.exists?(string)
21
+ end
22
+
23
+ def self.max(list)
24
+ max = nil
25
+ list.each do |v|
26
+ next if v.nil?
27
+ max = v if max.nil? or v > max
28
+ end
29
+ max
30
+ end
31
+
32
+ def self.google_venn(list1, list2, list3, name1 = nil, name2 = nil, name3 = nil, total = nil)
33
+ name1 ||= "list 1"
34
+ name2 ||= "list 2"
35
+ name3 ||= "list 3"
36
+
37
+ sizes = [list1, list2, list3, list1 & list2, list1 & list3, list2 & list3, list1 & list2 & list3].collect{|l| l.length}
38
+
39
+ total = total.length if Array === total
40
+
41
+ label = "#{name1}: #{sizes[0]} (#{name2}: #{sizes[3]}, #{name3}: #{sizes[4]})"
42
+ label << "|#{name2}: #{sizes[1]} (#{name1}: #{sizes[3]}, #{name3}: #{sizes[5]})"
43
+ label << "|#{name3}: #{sizes[2]} (#{name1}: #{sizes[4]}, #{name2}: #{sizes[5]})"
44
+ if total
45
+ label << "| INTERSECTION: #{sizes[6]} TOTAL: #{total}"
46
+ else
47
+ label << "| INTERSECTION: #{sizes[6]}"
48
+ end
49
+
50
+ max = total || sizes.max
51
+ sizes = sizes.collect{|v| (v.to_f/max * 100).to_i.to_f / 100}
52
+ url = "https://chart.googleapis.com/chart?cht=v&chs=500x300&chd=t:#{sizes * ","}&chco=FF6342,ADDE63,63C6DE,FFFFFF&chdl=#{label}"
53
+ end
54
+
55
+ def self.sum(list)
56
+ list.compact.inject(0.0){|acc,e| acc += e}
57
+ end
58
+
59
+ def self.mean(list)
60
+ sum(list) / list.compact.length
61
+ end
62
+
63
+ def self.sd(list)
64
+ return nil if list.length < 3
65
+ mean = mean(list)
66
+ Math.sqrt(list.compact.inject(0.0){|acc,e| d = e - mean; acc += d * d}) / (list.compact.length - 1)
67
+ end
68
+
10
69
  def self.consolidate(list)
11
70
  list.inject(nil){|acc,e|
12
71
  if acc.nil?
@@ -34,7 +93,7 @@ module Misc
34
93
  IndiferentHash.setup(options)
35
94
  options = Misc.add_defaults options, :from_alias => nil, :to_alias => nil, :server => 'localhost', :port => 25, :user => nil, :pass => nil, :auth => :login
36
95
  IndiferentHash.setup(options)
37
-
96
+
38
97
  server, port, user, pass, from_alias, to_alias, auth = Misc.process_options options, :server, :port, :user, :pass, :from_alias, :to_alias, :auth
39
98
 
40
99
  msg = <<-END_OF_MESSAGE
@@ -43,11 +102,11 @@ To: #{to_alias} <#{to}>
43
102
  Subject: #{subject}
44
103
 
45
104
  #{message}
46
- END_OF_MESSAGE
105
+ END_OF_MESSAGE
47
106
 
48
- Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
49
- smtp.send_message msg, from, to
50
- end
107
+ Net::SMTP.start(server, port, server, user, pass, auth) do |smtp|
108
+ smtp.send_message msg, from, to
109
+ end
51
110
  end
52
111
 
53
112
  def self.counts(array)
@@ -55,9 +114,34 @@ Subject: #{subject}
55
114
  array.each do |e|
56
115
  counts[e] += 1
57
116
  end
117
+
118
+ class << counts; self;end.class_eval do
119
+ def to_s
120
+ sort{|a,b| a[1] == b[1] ? a[0] <=> b[0] : a[1] <=> b[1]}.collect{|k,c| "%3d\t%s" % [c, k]} * "\n"
121
+ end
122
+ end
123
+
58
124
  counts
59
125
  end
60
126
 
127
+ def self.proportions(array)
128
+ total = array.length
129
+
130
+ proportions = Hash.new 0
131
+
132
+ array.each do |e|
133
+ proportions[e] += 1.0 / total
134
+ end
135
+
136
+ class << proportions; self;end.class_eval do
137
+ def to_s
138
+ sort{|a,b| a[1] == b[1] ? a[0] <=> b[0] : a[1] <=> b[1]}.collect{|k,c| "%3d\t%s" % [c, k]} * "\n"
139
+ end
140
+ end
141
+
142
+ proportions
143
+ end
144
+
61
145
  IUPAC2BASE = {
62
146
  "A" => ["A"],
63
147
  "C" => ["C"],
@@ -85,6 +169,29 @@ Subject: #{subject}
85
169
  "U" => "A",
86
170
  }
87
171
 
172
+ THREE_TO_ONE_AA_CODE = {
173
+ "ala" => "A",
174
+ "arg" => "R",
175
+ "asn" => "N",
176
+ "asp" => "D",
177
+ "cys" => "C",
178
+ "glu" => "E",
179
+ "gln" => "Q",
180
+ "gly" => "G",
181
+ "his" => "H",
182
+ "ile" => "I",
183
+ "leu" => "L",
184
+ "lys" => "K",
185
+ "met" => "M",
186
+ "phe" => "F",
187
+ "pro" => "P",
188
+ "ser" => "S",
189
+ "thr" => "T",
190
+ "trp" => "W",
191
+ "tyr" => "Y",
192
+ "val" => "V"
193
+ }
194
+
88
195
  def self.IUPAC_to_base(iupac)
89
196
  IUPAC2BASE[iupac]
90
197
  end
@@ -259,7 +366,7 @@ Subject: #{subject}
259
366
 
260
367
  def self.lock(file, *args)
261
368
  FileUtils.mkdir_p File.dirname(File.expand_path(file)) unless File.exists? File.dirname(File.expand_path(file))
262
- lockfile = Lockfile.new(file + '.lock')
369
+ lockfile = Lockfile.new(file + '.lock', :max_age => 1200, :suspend => 240)
263
370
  lockfile.lock do
264
371
  yield file, *args
265
372
  end
@@ -344,24 +451,34 @@ Subject: #{subject}
344
451
  end
345
452
 
346
453
  def self.hash2md5(hash)
347
- o = {}
454
+ str = ""
348
455
  hash.keys.sort_by{|k| k.to_s}.each do |k|
349
456
  next if k == :monitor or k == "monitor" or k == :in_situ_persistence or k == "in_situ_persistence"
350
457
  v = hash[k]
351
458
  case
352
- when v.inspect =~ /:0x0/
353
- o[k] = v.inspect.sub(/:0x[a-f0-9]+@/,'')
354
- #when Resource::Path === v
355
- # o[k] = "" << String.new(v.to_s)
459
+ when Hash === v
460
+ str << k.to_s << "=>" << hash2md5(v)
461
+ when Symbol === v
462
+ str << k.to_s << "=>" << v.to_s
463
+ when String === v
464
+ str << k.to_s << "=>" << v
356
465
  else
357
- o[k] = v
466
+ v_ins = v.inspect
467
+
468
+ case
469
+ when v_ins =~ /:0x0/
470
+ str << k.to_s << "=>" << v_ins.sub(/:0x[a-f0-9]+@/,'')
471
+ else
472
+ str << k.to_s << "=>" << v.to_s
473
+ end
474
+
358
475
  end
359
476
  end
360
477
 
361
- if o.empty?
478
+ if str.empty?
362
479
  ""
363
480
  else
364
- Digest::MD5.hexdigest(o.sort_by{|k| k.to_s}.inspect)
481
+ Digest::MD5.hexdigest(str)
365
482
  end
366
483
  end
367
484
 
@@ -455,7 +572,7 @@ Subject: #{subject}
455
572
  raise FieldNotFoundError, "Field information missing" if fields.nil? && ! quiet
456
573
  fields.each_with_index{|f,i| return i if f == field}
457
574
  field_re = Regexp.new /#{field}/i
458
- fields.each_with_index{|f,i| return i if f =~ field_re}
575
+ fields.each_with_index{|f,i| return i if f =~ field_re}
459
576
  raise FieldNotFoundError, "Field #{ field.inspect } was not found" unless quiet
460
577
  end
461
578
 
@@ -477,134 +594,6 @@ Subject: #{subject}
477
594
 
478
595
  end
479
596
 
480
- module NamedArray
481
- extend ChainMethods
482
-
483
- self.chain_prefix = :named_array
484
- attr_accessor :fields
485
- attr_accessor :key
486
-
487
- def self.setup(array, fields, key = nil)
488
- array.extend NamedArray
489
- array.fields = fields
490
- array.key = key
491
- array
492
- end
493
-
494
- def merge(array)
495
- double = Array === array.first
496
- new = self.dup
497
- (0..length - 1).each do |i|
498
- if double
499
- new[i] = new[i] + array[i]
500
- else
501
- new[i] << array[i]
502
- end
503
- end
504
- new
505
- end
506
-
507
- def positions(fields)
508
- if Array == fields
509
- fields.collect{|field|
510
- Misc.field_position(@fields, field)
511
- }
512
- else
513
- Misc.field_position(@fields, fields)
514
- end
515
- end
516
-
517
- def named_array_get_brackets(key)
518
- if defined? Entity
519
- entity = (defined?(Entity) and Entity.respond_to?(:formats)) ? Entity.formats[key] : nil
520
- if entity
521
- elem = if entity.annotations.first == :format
522
- entity.setup(named_array_clean_get_brackets(Misc.field_position(fields, key)), key)
523
- else
524
- entity.setup(named_array_clean_get_brackets(Misc.field_position(fields, key)))
525
- end
526
- elem.context = self
527
- elem
528
- else
529
- named_array_clean_get_brackets(Misc.field_position(fields, key))
530
- end
531
- else
532
- named_array_clean_get_brackets(Misc.field_position(fields, key))
533
- end
534
- end
535
-
536
- def named_array_each(&block)
537
- if defined?(Entity) and not @fields.nil? and not @fields.empty?
538
- @fields.zip(self).each do |field,elem|
539
- entity = (defined?(Entity) and Entity.respond_to?(:formats)) ? Entity.formats[field] : nil
540
-
541
- if entity
542
- elem = elem.dup if elem.frozen?
543
- if entity.annotations.first == :format
544
- entity.setup(elem, field)
545
- else
546
- entity.setup(elem)
547
- end
548
- elem.context = self
549
- elem
550
- end
551
-
552
- yield(elem)
553
- elem
554
- end
555
- else
556
- named_array_clean_each &block
557
- end
558
- end
559
-
560
- def named_array_collect
561
- res = []
562
-
563
- named_array_each do |elem|
564
- if block_given?
565
- res << yield(elem)
566
- else
567
- res << elem
568
- end
569
- end
570
-
571
- res
572
- end
573
-
574
- def named_array_set_brackets(key,value)
575
- named_array_clean_set_brackets(Misc.field_position(fields, key), value)
576
- end
577
-
578
- def named_array_values_at(*keys)
579
- keys = keys.collect{|k| Misc.field_position(fields, k) }
580
- named_array_clean_values_at(*keys)
581
- end
582
-
583
- def zip_fields
584
- return [] if self.empty?
585
- zipped = Misc.zip_fields(self)
586
- zipped = zipped.collect{|v| NamedArray.setup(v, fields)}
587
- zipped
588
- end
589
-
590
- def detach(file)
591
- file_fields = file.fields.collect{|field| field.fullname}
592
- detached_fields = []
593
- self.fields.each_with_index{|field,i| detached_fields << i if file_fields.include? field.fullname}
594
- fields = self.fields.values_at *detached_fields
595
- values = self.values_at *detached_fields
596
- values = NamedArray.name(values, fields)
597
- values.zip_fields
598
- end
599
-
600
- def report
601
- fields.zip(self).collect do |field,value|
602
- "#{ field }: #{ Array === value ? value * "|" : value }"
603
- end * "\n"
604
- end
605
-
606
- end
607
-
608
597
  class RBBTError < StandardError
609
598
  attr_accessor :info
610
599
 
@@ -664,7 +653,7 @@ module IndiferentHash
664
653
 
665
654
  def self.setup(hash)
666
655
  return hash if IndiferentHash === hash
667
- hash.extend IndiferentHash
656
+ hash.extend IndiferentHash unless IndiferentHash === hash
668
657
  hash
669
658
  end
670
659
  end