scout-gear 7.3.0 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +44 -16
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +21 -7
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/rbbt-scout.rb +1 -0
  9. data/lib/scout/cmd.rb +24 -25
  10. data/lib/scout/concurrent_stream.rb +59 -39
  11. data/lib/scout/config.rb +1 -1
  12. data/lib/scout/exceptions.rb +10 -0
  13. data/lib/scout/log/color.rb +15 -12
  14. data/lib/scout/log/progress/report.rb +8 -6
  15. data/lib/scout/log/progress/util.rb +61 -54
  16. data/lib/scout/log/progress.rb +1 -1
  17. data/lib/scout/log/trap.rb +107 -0
  18. data/lib/scout/log.rb +115 -52
  19. data/lib/scout/meta_extension.rb +47 -6
  20. data/lib/scout/misc/digest.rb +12 -3
  21. data/lib/scout/misc/format.rb +24 -7
  22. data/lib/scout/misc/insist.rb +1 -1
  23. data/lib/scout/misc/monitor.rb +22 -0
  24. data/lib/scout/misc/system.rb +58 -0
  25. data/lib/scout/named_array.rb +73 -3
  26. data/lib/scout/offsite/ssh.rb +171 -0
  27. data/lib/scout/offsite/step.rb +83 -0
  28. data/lib/scout/offsite/sync.rb +55 -0
  29. data/lib/scout/offsite.rb +3 -0
  30. data/lib/scout/open/lock/lockfile.rb +587 -0
  31. data/lib/scout/open/lock.rb +9 -2
  32. data/lib/scout/open/remote.rb +16 -1
  33. data/lib/scout/open/stream.rb +146 -83
  34. data/lib/scout/open/util.rb +22 -3
  35. data/lib/scout/open.rb +5 -4
  36. data/lib/scout/path/find.rb +24 -11
  37. data/lib/scout/path/util.rb +40 -0
  38. data/lib/scout/persist/serialize.rb +19 -6
  39. data/lib/scout/persist.rb +29 -13
  40. data/lib/scout/resource/path.rb +57 -0
  41. data/lib/scout/resource/produce.rb +0 -8
  42. data/lib/scout/resource/util.rb +12 -5
  43. data/lib/scout/tmpfile.rb +7 -8
  44. data/lib/scout/tsv/attach.rb +177 -0
  45. data/lib/scout/tsv/change_id.rb +40 -0
  46. data/lib/scout/tsv/dumper.rb +74 -46
  47. data/lib/scout/tsv/index.rb +85 -87
  48. data/lib/scout/tsv/open.rb +160 -85
  49. data/lib/scout/tsv/parser.rb +142 -80
  50. data/lib/scout/tsv/path.rb +1 -2
  51. data/lib/scout/tsv/persist/adapter.rb +15 -45
  52. data/lib/scout/tsv/persist/fix_width_table.rb +3 -0
  53. data/lib/scout/tsv/persist/tokyocabinet.rb +6 -1
  54. data/lib/scout/tsv/persist.rb +4 -0
  55. data/lib/scout/tsv/stream.rb +204 -0
  56. data/lib/scout/tsv/transformer.rb +152 -0
  57. data/lib/scout/tsv/traverse.rb +96 -92
  58. data/lib/scout/tsv/util/filter.rb +9 -0
  59. data/lib/scout/tsv/util/reorder.rb +81 -0
  60. data/lib/scout/tsv/util/select.rb +78 -33
  61. data/lib/scout/tsv/util/unzip.rb +86 -0
  62. data/lib/scout/tsv/util.rb +60 -11
  63. data/lib/scout/tsv.rb +34 -4
  64. data/lib/scout/work_queue/socket.rb +6 -1
  65. data/lib/scout/work_queue/worker.rb +5 -2
  66. data/lib/scout/work_queue.rb +51 -20
  67. data/lib/scout/workflow/definition.rb +23 -3
  68. data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
  69. data/lib/scout/workflow/deployment.rb +1 -0
  70. data/lib/scout/workflow/step/dependencies.rb +56 -10
  71. data/lib/scout/workflow/step/file.rb +5 -0
  72. data/lib/scout/workflow/step/info.rb +40 -7
  73. data/lib/scout/workflow/step/load.rb +1 -1
  74. data/lib/scout/workflow/step/provenance.rb +9 -7
  75. data/lib/scout/workflow/step/status.rb +43 -0
  76. data/lib/scout/workflow/step.rb +160 -49
  77. data/lib/scout/workflow/task/dependencies.rb +114 -0
  78. data/lib/scout/workflow/task/inputs.rb +40 -32
  79. data/lib/scout/workflow/task.rb +38 -102
  80. data/lib/scout/workflow/usage.rb +48 -18
  81. data/lib/scout/workflow.rb +4 -2
  82. data/lib/scout-gear.rb +2 -0
  83. data/lib/scout.rb +6 -0
  84. data/scout-gear.gemspec +52 -23
  85. data/scout_commands/doc +37 -0
  86. data/scout_commands/find +1 -0
  87. data/scout_commands/offsite +30 -0
  88. data/scout_commands/update +29 -0
  89. data/scout_commands/workflow/info +15 -3
  90. data/scout_commands/workflow/install +102 -0
  91. data/scout_commands/workflow/task +57 -9
  92. data/test/scout/offsite/test_ssh.rb +15 -0
  93. data/test/scout/offsite/test_step.rb +33 -0
  94. data/test/scout/offsite/test_sync.rb +36 -0
  95. data/test/scout/offsite/test_task.rb +0 -0
  96. data/test/scout/open/test_stream.rb +60 -58
  97. data/test/scout/path/test_find.rb +10 -1
  98. data/test/scout/resource/test_path.rb +6 -0
  99. data/test/scout/resource/test_produce.rb +15 -0
  100. data/test/scout/test_meta_extension.rb +25 -0
  101. data/test/scout/test_named_array.rb +24 -0
  102. data/test/scout/test_persist.rb +9 -2
  103. data/test/scout/test_tsv.rb +229 -2
  104. data/test/scout/test_work_queue.rb +65 -41
  105. data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
  106. data/test/scout/tsv/test_attach.rb +227 -0
  107. data/test/scout/tsv/test_change_id.rb +98 -0
  108. data/test/scout/tsv/test_dumper.rb +1 -1
  109. data/test/scout/tsv/test_index.rb +49 -3
  110. data/test/scout/tsv/test_open.rb +160 -2
  111. data/test/scout/tsv/test_parser.rb +33 -2
  112. data/test/scout/tsv/test_persist.rb +2 -0
  113. data/test/scout/tsv/test_stream.rb +200 -0
  114. data/test/scout/tsv/test_transformer.rb +120 -0
  115. data/test/scout/tsv/test_traverse.rb +88 -3
  116. data/test/scout/tsv/test_util.rb +1 -0
  117. data/test/scout/tsv/util/test_reorder.rb +94 -0
  118. data/test/scout/tsv/util/test_select.rb +25 -11
  119. data/test/scout/tsv/util/test_unzip.rb +112 -0
  120. data/test/scout/work_queue/test_socket.rb +0 -1
  121. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  122. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  123. data/test/scout/workflow/step/test_info.rb +18 -0
  124. data/test/scout/workflow/step/test_status.rb +30 -0
  125. data/test/scout/workflow/task/test_dependencies.rb +355 -0
  126. data/test/scout/workflow/task/test_inputs.rb +67 -14
  127. data/test/scout/workflow/test_definition.rb +18 -0
  128. data/test/scout/workflow/test_documentation.rb +24 -0
  129. data/test/scout/workflow/test_step.rb +112 -3
  130. data/test/scout/workflow/test_task.rb +0 -151
  131. data/test/scout/workflow/test_usage.rb +33 -6
  132. data/test/test_scout.rb +9 -0
  133. metadata +100 -8
  134. data/scout_commands/workflow/task_old +0 -706
@@ -12,17 +12,24 @@ module TSV
12
12
  end
13
13
  end
14
14
 
15
- def self.parse_line(line, type: :list, key: 0, positions: nil, sep: "\t", sep2: "|", cast: nil)
15
+ def self.parse_line(line, type: :list, key: 0, positions: nil, sep: "\t", sep2: "|", cast: nil, select: nil, field_names: nil)
16
16
  items = line.split(sep, -1)
17
17
 
18
+ return nil if select && ! TSV.select(items[0], items[1..-1], select, fields: field_names, type: type, sep: sep2)
19
+
18
20
  if positions.nil? && key == 0
19
21
  key = items.shift
20
- elsif positions.nil?
21
- key = items.delete_at(key)
22
+ elsif positions.nil?
23
+ if type == :flat
24
+ key = items[1..-1].collect{|e| e.split(sep2, -1) }.flatten
25
+ items = items.slice(0,1)
26
+ else
27
+ key = items.delete_at(key)
28
+ end
22
29
  key = key.split(sep2) if type == :double
23
30
  else
24
31
  key, items = items[key], items.values_at(*positions)
25
- key = key.split(sep2) if type == :double
32
+ key = key.split(sep2) if type == :double || type == :flat
26
33
  end
27
34
 
28
35
  items = case type
@@ -31,9 +38,9 @@ module TSV
31
38
  when :single
32
39
  items.first
33
40
  when :flat
34
- [items]
41
+ items.collect{|i| i.split(sep2, -1) }.flatten
35
42
  when :double
36
- items.collect{|i| i.split(sep2, -1) }
43
+ items.collect{|i| i.nil? ? [] : i.split(sep2, -1) }
37
44
  end
38
45
 
39
46
 
@@ -44,21 +51,34 @@ module TSV
44
51
  [key, items]
45
52
  end
46
53
 
47
- def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, **kargs, &block)
54
+ def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, **kargs, &block)
48
55
  begin
49
- bar = Log::ProgressBar.new_bar(bar) if bar
56
+ bar = "Parsing #{Log.fingerprint stream}" if TrueClass === bar
57
+ bar = Log::ProgressBar.get_obj_bar(stream, bar) if bar
58
+ bar.init if bar
50
59
 
51
60
  source_type = type if source_type.nil?
52
61
 
53
62
  data = {} if data.nil?
54
- merge = false if type != :double
63
+ merge = false if type != :double && type != :flat
55
64
  line = first_line || stream.gets
56
65
  while line
57
66
  begin
58
- line.strip!
59
- line = Misc.fixutf8(line) if fix
67
+ line.chomp!
68
+ if Proc === fix
69
+ line = fix.call line
70
+ elsif fix
71
+ line = Misc.fixutf8(line)
72
+ end
60
73
  bar.tick if bar
61
- key, items = parse_line(line, type: source_type, **kargs)
74
+ if type == :array || type == :line
75
+ block.call line
76
+ next
77
+ end
78
+
79
+ key, items = parse_line(line, type: source_type, field_names: field_names, **kargs)
80
+
81
+ next if key.nil?
62
82
 
63
83
  if Array === key
64
84
  keys = key
@@ -116,44 +136,68 @@ module TSV
116
136
  end
117
137
 
118
138
  if block_given?
119
- res = block.call(key, these_items)
139
+ res = block.call(key, these_items, field_names)
120
140
  data[key] = res unless res.nil? || FalseClass === data
121
141
  next
122
142
  end
123
143
 
124
144
  if ! merge || ! data.include?(key)
125
145
  data[key] = these_items
126
- else
146
+ elsif type == :double
127
147
  current = data[key]
128
148
  if merge == :concat
129
149
  these_items.each_with_index do |new,i|
130
- next if new.empty?
150
+ new = [nil] if new.empty?
131
151
  current[i].concat(new)
132
152
  end
133
153
  else
134
154
  merged = []
135
155
  these_items.each_with_index do |new,i|
136
- next if new.empty?
156
+ new = [nil] if new.empty?
137
157
  merged[i] = current[i] + new
138
158
  end
139
159
  data[key] = merged
140
160
  end
161
+ elsif type == :flat
162
+ current = data[key]
163
+ if merge == :concat
164
+ current[i].concat these_items
165
+ else
166
+ data[key] = current + these_items
167
+ end
141
168
  end
142
169
  end
170
+ rescue Exception
171
+ stream.abort($!) if stream.respond_to?(:abort)
172
+ raise $!
143
173
  ensure
144
- line = stream.gets
174
+ if stream.closed?
175
+ line = nil
176
+ else
177
+ line = stream.gets
178
+ end
145
179
  end
146
180
  end
147
181
  data
148
182
  ensure
149
- Log::ProgressBar.remove_bar(bar) if bar
183
+ if stream.stream_exception
184
+ bar.remove(stream.stream_exception)
185
+ else
186
+ bar.remove
187
+ end if bar
188
+ stream.join if stream.respond_to?(:join)
150
189
  end
151
190
  end
152
191
 
153
192
  def self.parse_header(stream, fix: true, header_hash: '#', sep: "\t")
193
+ if (Path === stream) || ((String === stream) && Path.is_filename?(stream))
194
+ Open.open(stream) do |f|
195
+ return parse_header(f, fix: fix, header_hash: header_hash, sep: sep)
196
+ end
197
+ end
154
198
  raise "Closed stream" if IO === stream && stream.closed?
155
199
 
156
- options = {}
200
+ opts = {}
157
201
  preamble = []
158
202
 
159
203
  # Get line
@@ -165,13 +209,19 @@ module TSV
165
209
 
166
210
  # Process options line
167
211
  if line and (String === header_hash && m = line.match(/^#{header_hash}: (.*)/))
168
- options = IndiferentHash.string2hash m.captures.first.chomp
212
+ opts = IndiferentHash.string2hash m.captures.first.chomp
169
213
  line = stream.gets
170
- line = Misc.fixutf8 line.chomp if line && fix
214
+ if line && fix
215
+ if Proc === fix
216
+ line = fix.call line
217
+ else
218
+ line = Misc.fixutf8 line.chomp if line && fix
219
+ end
220
+ end
171
221
  end
172
222
 
173
223
  # Determine separator
174
- sep = options[:sep] if options[:sep]
224
+ sep = opts[:sep] if opts[:sep]
175
225
 
176
226
  # Process fields line
177
227
  preamble << line if line
@@ -192,7 +242,10 @@ module TSV
192
242
 
193
243
  first_line = line
194
244
 
195
- [options, key_field, fields, first_line, preamble]
245
+ opts[:type] = opts[:type].to_sym if opts[:type]
246
+ opts[:cast] = opts[:cast].to_sym if opts[:cast]
247
+
248
+ NamedArray.setup([opts, key_field, fields, first_line, preamble], %w(options key_field fields first_line preamble))
196
249
  end
197
250
 
198
251
  KEY_PARAMETERS = begin
@@ -204,43 +257,81 @@ module TSV
204
257
  end
205
258
 
206
259
  class Parser
207
- attr_accessor :stream, :options, :key_field, :fields, :first_line, :preamble
208
- def initialize(file, fix: true, header_hash: "#", sep: "\t")
260
+ attr_accessor :stream, :options, :key_field, :fields, :type, :first_line, :preamble
261
+ def initialize(file, fix: true, header_hash: "#", sep: "\t", type: :double)
209
262
  if IO === file
210
263
  @stream = file
211
264
  else
212
265
  @stream = Open.open(file)
213
266
  end
267
+ @fix = fix
214
268
  @options, @key_field, @fields, @first_line, @preamble = TSV.parse_header(@stream, fix:fix, header_hash:header_hash, sep:sep)
215
269
  @options[:sep] = sep if @options[:sep].nil?
270
+ @options.merge!(:key_field => @key_field, :fields => @fields)
271
+ @type = @options[:type] || type
216
272
  end
217
273
 
218
274
  def all_fields
275
+ return nil if @fields.nil?
219
276
  [@key_field] + @fields
220
277
  end
221
278
 
279
+ def key_field=(key_field)
280
+ @options[:key_field] = @key_field = key_field
281
+ end
282
+
283
+ def fields=(fields)
284
+ @options[:fields] = @fields = fields
285
+ end
286
+
287
+ def identify_field(name)
288
+ TSV.identify_field(@key_field, @fields, name)
289
+ end
290
+
222
291
  def traverse(key_field: nil, fields: nil, filename: nil, namespace: nil, **kwargs, &block)
292
+ kwargs[:type] ||= self.options[:type] ||= @type
293
+ kwargs[:type] = kwargs[:type].to_sym if kwargs[:type]
294
+
223
295
  if fields
224
- all_field_names ||= [@key_field] + @fields
225
- positions = NamedArray.identify_name(all_field_names, fields)
226
- kwargs[:positions] = positions
227
- field_names = all_field_names.values_at *positions
296
+ if @fields
297
+ all_field_names ||= [@key_field] + @fields
298
+ fields = all_field_names if fields == :all
299
+ positions = NamedArray.identify_name(all_field_names, fields)
300
+ kwargs[:positions] = positions
301
+ field_names = all_field_names.values_at *positions
302
+ elsif fields.reject{|f| Numeric === f}.empty?
303
+ positions = fields
304
+ kwargs[:positions] = positions
305
+ else
306
+ raise "Non-numeric fields specified, but no field names available"
307
+ end
228
308
  else
229
309
  field_names = @fields
230
310
  end
231
311
 
312
+ kwargs[:positions] = nil if @type == :flat
313
+
232
314
  if key_field
233
- all_field_names ||= [@key_field] + @fields
234
- key = NamedArray.identify_name(all_field_names, key_field)
235
- kwargs[:key] = key == :key ? 0 : key
236
- key_field_name = key === :key ? @key_field : all_field_names[key]
237
- if fields.nil?
238
- field_names = all_field_names - [@key_field]
315
+ if @fields
316
+ all_field_names ||= [@key_field] + @fields
317
+ key = NamedArray.identify_name(all_field_names, key_field)
318
+ kwargs[:key] = key == :key ? 0 : key
319
+ key_field_name = key === :key ? @key_field : all_field_names[key]
320
+ if fields.nil?
321
+ field_names = all_field_names - [key_field_name]
322
+ end
323
+ else
324
+ kwargs[:key] = key_field == :key ? 0 : key_field
325
+ key = key_field
239
326
  end
240
327
  else
241
328
  key_field_name = @key_field
242
329
  end
243
330
 
331
+ if field_names && (kwargs[:type] == :single || kwargs[:type] == :flat)
332
+ field_names = field_names.slice(0,1)
333
+ end
334
+
244
335
  @options.each do |option,value|
245
336
  option = option.to_sym
246
337
  next unless KEY_PARAMETERS.include? option
@@ -250,21 +341,33 @@ module TSV
250
341
  kwargs[:source_type] = @options[:type]
251
342
  kwargs[:data] = false if kwargs[:data].nil?
252
343
 
253
- data = TSV.parse_stream(@stream, first_line: @first_line, **kwargs, &block)
344
+ data = TSV.parse_stream(@stream, first_line: @first_line, fix: @fix, field_names: @fields, **kwargs, &block)
254
345
 
255
346
  if data
256
347
  TSV.setup(data, :key_field => key_field_name, :fields => field_names, :type => @type)
257
348
  else
258
- self
349
+ [self.key_field, self.fields]
259
350
  end
260
351
  end
261
352
 
353
+ def fingerprint
354
+ "Parser:{"<< Log.fingerprint(self.all_fields|| []) << "}"
355
+ end
356
+
357
+ def digest_str
358
+ fingerprint
359
+ end
360
+
361
+ def inspect
362
+ fingerprint
363
+ end
262
364
  end
263
365
 
264
366
  def self.parse(stream, fix: true, header_hash: "#", sep: "\t", filename: nil, namespace: nil, unnamed: false, serializer: nil, **kwargs, &block)
265
367
  parser = TSV::Parser.new stream, fix: fix, header_hash: header_hash, sep: sep
266
368
 
267
- cast = parser.options[:cast] || kwargs[:cast]
369
+ cast = kwargs[:cast]
370
+ cast = parser.options[:cast] if cast.nil?
268
371
  type = kwargs[:type] ||= parser.options[:type] ||= :double
269
372
  if (data = kwargs[:data]) && data.respond_to?(:persistence_class)
270
373
  TSV.setup(data, type: type)
@@ -297,48 +400,7 @@ module TSV
297
400
  data.filename = filename
298
401
  data.namespace = namespace
299
402
  data.unnamed = unnamed
403
+ data.save_extension_attr_hash if data.respond_to?(:save_extension_attr_hash)
300
404
  data
301
405
  end
302
-
303
- #def self.parse_alt(stream, key_field: nil, fields: nil, filename: nil, namespace: nil, **kwargs, &block)
304
- # options, key_field_name, field_names, first_line, preamble = parse_header(stream)
305
-
306
- # if fields
307
- # all_field_names ||= [key_field_name] + field_names
308
- # positions = NamedArray.identify_name(all_field_names, fields)
309
- # kwargs[:positions] = positions
310
- # field_names = all_field_names.values_at *positions
311
- # end
312
-
313
- # if key_field
314
- # all_field_names ||= [key_field_name] + field_names
315
- # key = NamedArray.identify_name(all_field_names, key_field)
316
- # kwargs[:key] = key
317
- # key_field_name = all_field_names[key]
318
- # if fields.nil?
319
- # field_names = all_field_names - [key_field_name]
320
- # end
321
- # end
322
-
323
- # options.each do |option,value|
324
- # option = option.to_sym
325
- # next unless KEY_PARAMETERS.include? option
326
- # kwargs[option] = value unless kwargs.include?(option)
327
- # end
328
-
329
- # kwargs[:source_type] = options[:type]
330
-
331
- # type = kwargs[:type] ||= :double
332
- # if (data = kwargs[:data]) && data.respond_to?(:persistence_class)
333
- # TSV.setup(data, type: type, key_field: key_field_name, fields: field_names)
334
- # data.extend TSVAdapter
335
- # end
336
-
337
- # data = parse_stream(stream, first_line: first_line, **kwargs, &block)
338
-
339
- # TSV.setup(data, :key_field => key_field_name, :fields => field_names, :type => type, filename: filename, namespace: namespace)
340
-
341
- # data
342
- #end
343
-
344
406
  end
@@ -1,7 +1,6 @@
1
1
  module Path
2
2
  def tsv(*args, **kwargs, &block)
3
- found = self.find
4
- found = self.set_extension('tsv').find unless found.exists?
3
+ found = produce_and_find('tsv')
5
4
  TSV.open(found, *args, **kwargs, &block)
6
5
  end
7
6
 
@@ -1,8 +1,9 @@
1
1
  require_relative '../../open/lock'
2
+ require_relative '../../meta_extension'
2
3
  require_relative 'serialize'
3
4
 
4
5
  module TSVAdapter
5
- attr_accessor :persistence_path, :persistence_class, :serializer, :closed, :writable
6
+ attr_accessor :persistence_path, :persistence_class, :closed, :writable, :serializer
6
7
 
7
8
  class << self
8
9
  attr_accessor :lock_dir
@@ -19,23 +20,15 @@ module TSVAdapter
19
20
  end
20
21
 
21
22
  def load_extension_attr_hash
22
- EXTENSION_ATTR_HASH_SERIALIZER.load(StringIO.new(self[EXTENSION_ATTR_HASH_KEY]))
23
+ EXTENSION_ATTR_HASH_SERIALIZER.load(StringIO.new(self.orig_get(EXTENSION_ATTR_HASH_KEY)))
23
24
  end
24
25
 
25
26
  def save_extension_attr_hash
26
- self[EXTENSION_ATTR_HASH_KEY]= EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash)
27
+ self.orig_set(EXTENSION_ATTR_HASH_KEY, EXTENSION_ATTR_HASH_SERIALIZER.dump(self.extension_attr_hash))
27
28
  end
28
29
 
29
30
  def self.extended(base)
30
- if ! TSVAdapter === base
31
- if (! TSVAdapter === base) && base.include?(EXTENSION_ATTR_HASH_KEY)
32
- TSV.setup(base, base.load_extension_attr_hash)
33
- elsif TSV === base
34
- base[EXTENSION_ATTR_HASH_KEY] = EXTENSION_ATTR_HASH_SERIALIZER.dump(base.extension_attr_hash)
35
- end
36
- end
37
-
38
- base.serializer = SERIALIZER_ALIAS[base.type]
31
+ return if base.respond_to?(:orig_set)
39
32
 
40
33
  class << base
41
34
  alias orig_set []=
@@ -54,45 +47,22 @@ module TSVAdapter
54
47
  end
55
48
 
56
49
  def load_value(str)
50
+ return nil if str.nil?
57
51
  serializer.load(str)
58
52
  end
59
53
 
60
54
  def save_value(value)
61
55
  serializer.dump(value)
62
56
  end
63
-
64
-
65
57
  end
66
58
 
67
- #case base.type
68
- #when :single
69
- # class << base
70
- # def load_value(value)
71
- # value
72
- # end
73
- # def save_value(value)
74
- # value
75
- # end
76
- # end
77
- #when :list, :flat
78
- # class << base
79
- # def load_value(value)
80
- # value.nil? ? nil : value.split("\t")
81
- # end
82
- # def save_value(value)
83
- # value * "\t"
84
- # end
85
- # end
86
- #when :double
87
- # class << base
88
- # def load_value(value)
89
- # value.nil? ? nil : value.split("\t").collect{|v| v.split("|") }
90
- # end
91
- # def save_value(value)
92
- # value.collect{|v| v * "|" } * "\t"
93
- # end
94
- # end
95
- #end
59
+ if base.include?(EXTENSION_ATTR_HASH_KEY)
60
+ TSV.setup(base, base.load_extension_attr_hash)
61
+ else
62
+ base.instance_variable_get(:@extension_attrs).push :serializer
63
+ base.serializer = SERIALIZER_ALIAS[base.type] if base.serializer.nil?
64
+ base.save_extension_attr_hash
65
+ end
96
66
  end
97
67
 
98
68
  def keys(*args)
@@ -101,9 +71,9 @@ module TSVAdapter
101
71
  end
102
72
 
103
73
  if k[0] == EXTENSION_ATTR_HASH_KEY
104
- k.slice(1,k.length-1)
74
+ k.slice(1,k.length)
105
75
  elsif k[-1] == EXTENSION_ATTR_HASH_KEY
106
- k.slice(0,k.length-2)
76
+ k.slice(0,k.length-1)
107
77
  else
108
78
  k - [EXTENSION_ATTR_HASH_KEY]
109
79
  end
@@ -2,6 +2,7 @@ class FixWidthTable
2
2
 
3
3
  attr_accessor :filename, :file, :value_size, :record_size, :range, :size, :mask, :write
4
4
  def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true)
5
+ filename = filename.find if Path === filename
5
6
  @filename = filename
6
7
 
7
8
  if update || %w(memory stringio).include?(filename.to_s.downcase) || ! File.exist?(filename)
@@ -312,6 +313,8 @@ class FixWidthTable
312
313
  acc.concat(new)
313
314
  end
314
315
  end
316
+
317
+ alias length size
315
318
  end
316
319
 
317
320
  Persist.save_drivers[:fwt] = proc do |file, content|
@@ -16,10 +16,13 @@ module ScoutCabinet
16
16
  dir = File.dirname(File.expand_path(path))
17
17
  Open.mkdir(dir) unless File.exist?(dir)
18
18
 
19
+ tokyocabinet_class = tokyocabinet_class.to_s if Symbol === tokyocabinet_class
19
20
  tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
20
21
  tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
21
22
 
22
- database = Persist::CONNECTIONS[path] ||= tokyocabinet_class.new
23
+ # Hack - Ignore warning: undefining the allocator of T_DATA class
24
+ # TokyoCabinet::HDB_data
25
+ database = Log.ignore_stderr do Persist::CONNECTIONS[path] ||= tokyocabinet_class.new end
23
26
 
24
27
  if big and not Open.exists?(path)
25
28
  database.tune(nil,nil,nil,tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
@@ -39,6 +42,8 @@ module ScoutCabinet
39
42
 
40
43
  database.open(path, tokyocabinet_class::OREADER)
41
44
 
45
+ database.define_singleton_method(:fingerprint){ "#{self.persistence_class}:#{self.persistence_path}" }
46
+
42
47
  Persist::CONNECTIONS[path] = database
43
48
 
44
49
  database
@@ -6,6 +6,10 @@ Persist.save_drivers[:tsv] = proc do |file,content|
6
6
  content
7
7
  elsif content.respond_to?(:stream)
8
8
  content.stream
9
+ elsif content.respond_to?(:dumper_stream)
10
+ content.dumper_stream
11
+ else
12
+ content
9
13
  end
10
14
  Open.sensible_write(file, stream)
11
15
  end